Skip to content

Commit 4a627d0

Browse files
authored
Custom date picker and custom component improvements (#26)
1 parent 60fce08 commit 4a627d0

File tree

14 files changed

+790
-394
lines changed

14 files changed

+790
-394
lines changed

demo/package.json

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,29 @@
66
"dependencies": {
77
"@chakra-ui/icons": "^2.1.1",
88
"@chakra-ui/react": "^2.8.2",
9-
"@emotion/react": "^11.11.1",
9+
"@emotion/react": "^11.11.3",
1010
"@emotion/styled": "^11.11.0",
11-
"@testing-library/jest-dom": "^6.1.4",
12-
"@testing-library/react": "^14.1.0",
13-
"@testing-library/user-event": "^14.5.1",
14-
"@types/jest": "^29.5.8",
15-
"@types/node": "^20.9.0",
16-
"@types/react": "^18.2.37",
17-
"@types/react-dom": "^18.2.15",
18-
"firebase": "^9.22.1",
19-
"framer-motion": "^10.16.5",
20-
"json-edit-react": "^1.2.0",
11+
"@testing-library/jest-dom": "^6.3.0",
12+
"@testing-library/react": "^14.1.2",
13+
"@testing-library/user-event": "^14.5.2",
14+
"@types/jest": "^29.5.11",
15+
"@types/node": "^20.11.6",
16+
"@types/react": "^18.2.48",
17+
"@types/react-dom": "^18.2.18",
18+
"firebase": "^10.7.2",
19+
"framer-motion": "^11.0.3",
20+
"json-edit-react": "^1.2.1",
2121
"just-clone": "^6.2.0",
2222
"just-compare": "^2.3.0",
2323
"react": "^18.2.0",
24+
"react-datepicker": "^5.0.0",
2425
"react-dom": "^18.2.0",
2526
"react-firebase-hooks": "^5.1.1",
26-
"react-icons": "^4.12.0",
27+
"react-icons": "^5.0.1",
2728
"react-scripts": "5.0.1",
28-
"typescript": "^5.2.2",
29+
"typescript": "^5.3.3",
2930
"use-undo": "^1.1.1",
30-
"web-vitals": "^3.5.0"
31+
"web-vitals": "^3.5.2"
3132
},
3233
"scripts": {
3334
"start": "rimraf ./src/json-edit-react && mkdir ./src/json-edit-react && mkdir ./src/json-edit-react/src && concurrently --kill-others-on-fail \"PORT=3008 react-scripts start\" \"nodemon watch.js\"",
@@ -65,8 +66,8 @@
6566
},
6667
"devDependencies": {
6768
"concurrently": "^8.2.2",
68-
"gh-pages": "^6.0.0",
69+
"gh-pages": "^6.1.1",
6970
"node-fetch": "^3.3.2",
70-
"nodemon": "^3.0.1"
71+
"nodemon": "^3.0.3"
7172
}
7273
}

demo/src/App.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1+
import DatePicker from 'react-datepicker'
2+
import 'react-datepicker/dist/react-datepicker.css'
3+
14
import React, { useEffect, useRef } from 'react'
2-
/* Local version */
3-
// import { JsonEditor, themes, ThemeName, Theme, ThemeInput } from './json-edit-react/src'
4-
/* npm version */
5-
import { JsonEditor, themes, ThemeName, Theme, ThemeInput } from 'json-edit-react'
6-
/* Local built version */
7-
// import { JsonEditor, themes, ThemeName, Theme, ThemeInput } from './package'
5+
import { JsonEditor, themes, ThemeName, Theme, ThemeInput } from './JsonEditImport'
86
import { FaNpm, FaExternalLinkAlt, FaGithub } from 'react-icons/fa'
97
import { BiReset } from 'react-icons/bi'
108
import { AiOutlineCloudUpload } from 'react-icons/ai'

demo/src/JsonEditImport.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* Local version */
2+
import {
3+
JsonEditor,
4+
themes,
5+
Theme,
6+
ThemeName,
7+
ThemeInput,
8+
CustomNodeProps,
9+
CustomNodeDefinition,
10+
FilterFunction,
11+
} from './json-edit-react/src'
12+
13+
/* npm version */
14+
// import {
15+
// JsonEditor,
16+
// themes,
17+
// ThemeName,
18+
// Theme,
19+
// ThemeInput,
20+
// CustomNodeProps,
21+
// CustomNodeDefinition,
22+
// FilterFunction,
23+
// } from 'json-edit-react'
24+
25+
/* Local built version */
26+
// import {
27+
// JsonEditor,
28+
// themes,
29+
// ThemeName,
30+
// Theme,
31+
// ThemeInput,
32+
// CustomNodeProps,
33+
// CustomNodeDefinition,
34+
// FilterFunction,
35+
// } from './package'
36+
37+
export {
38+
JsonEditor,
39+
themes,
40+
type Theme,
41+
type ThemeName,
42+
type ThemeInput,
43+
type CustomNodeProps,
44+
type CustomNodeDefinition,
45+
type FilterFunction,
46+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/**
2+
* An example Custom Component:
3+
* https://github.com/CarlosNZ/json-edit-react#custom-nodes
4+
*
5+
* A date/time picker which can be configure to show (using the
6+
* CustomNodeDefinitions at the bottom of this file) when an ISO date/time
7+
* string is present in the JSON data, and present a Date picker interface
8+
* rather than requiring the user to edit the ISO string directly.
9+
*/
10+
11+
import React from 'react'
12+
import DatePicker from 'react-datepicker'
13+
import { Button } from '@chakra-ui/react'
14+
import { CustomNodeProps, CustomNodeDefinition } from '../JsonEditImport'
15+
16+
// Styles
17+
import 'react-datepicker/dist/react-datepicker.css'
18+
// For better matching with Chakra-UI
19+
import './style.css'
20+
21+
export const DateTimePicker: React.FC<CustomNodeProps> = ({
22+
value,
23+
setValue,
24+
handleEdit,
25+
handleCancel,
26+
handleKeyPress,
27+
isEditing,
28+
setIsEditing,
29+
styles,
30+
customProps,
31+
}) => {
32+
const { dateFormat = 'MMM d, yyyy h:mm aa', showTimeSelect = true } = customProps ?? {}
33+
34+
const date = new Date(value as string)
35+
36+
return isEditing ? (
37+
// Picker only shows up when "editing". Due to the `showOnView: false` in
38+
// the definition below, this component will not show at all when viewing
39+
// (and so will show raw ISO strings). However, we've defined an alternative
40+
// here too, when showOnView == true, in which case the date/time string is
41+
// shown as a localised date/time.
42+
<DatePicker
43+
// Check to prevent invalid date (from previous data value) crashing the
44+
// component
45+
selected={isNaN(date as any) ? null : date}
46+
showTimeSelect={showTimeSelect}
47+
dateFormat={dateFormat}
48+
onChange={(date: Date) => setValue(date.toISOString())}
49+
open={true}
50+
onKeyDown={handleKeyPress}
51+
>
52+
<div style={{ display: 'flex', gap: 20 }}>
53+
{/* These buttons are not really necessary -- you can either use the
54+
standard Ok/Cancel icons, or keyboard Enter/Esc, but shown for demo
55+
purposes */}
56+
<Button
57+
color={styles.container.backgroundColor}
58+
backgroundColor={styles.iconOk.color}
59+
onClick={handleEdit}
60+
>
61+
OK
62+
</Button>
63+
<Button
64+
color={styles.container.backgroundColor}
65+
backgroundColor={styles.iconCancel.color}
66+
onClick={handleCancel}
67+
>
68+
Cancel
69+
</Button>
70+
</div>
71+
</DatePicker>
72+
) : (
73+
<div
74+
// Double-click behaviour same as standard elements
75+
onDoubleClick={() => setIsEditing(true)}
76+
className="jer-value-string"
77+
style={styles.string}
78+
>
79+
"{new Date(value as string).toLocaleDateString()}"
80+
</div>
81+
)
82+
}
83+
84+
// Definition for custom node behaviour
85+
export const dateNodeDefinition: CustomNodeDefinition = {
86+
// Condition is a regex to match ISO strings
87+
condition: ({ value }) =>
88+
typeof value === 'string' &&
89+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[\d\.]*(Z?|[\+-][\d:]+)$/.test(value),
90+
element: DateTimePicker, // the component defined above
91+
showOnView: false,
92+
showOnEdit: true,
93+
name: 'Date', // shown in the Type selector menu
94+
showInTypesSelector: true,
95+
defaultValue: new Date().toISOString(), // when instantiated, default to the current date/time
96+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/* Styles to make Date picker more like Chakra-UI
2+
From https://github.com/chakra-ui/chakra-ui/issues/580#issuecomment-653527951
3+
*/
4+
5+
.react-datepicker {
6+
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
7+
sans-serif;
8+
overflow: hidden;
9+
}
10+
11+
react-datepicker__navigation--next--with-time:not(
12+
.react-datepicker__navigation--next--with-today-button
13+
) {
14+
right: 90px;
15+
}
16+
17+
/* .react-datepicker__navigation--previous,
18+
.react-datepicker__navigation--next {
19+
height: 8px;
20+
} */
21+
22+
.react-datepicker__navigation--previous {
23+
border-right-color: #cbd5e0;
24+
25+
&:hover {
26+
border-right-color: #a0aec0;
27+
}
28+
}
29+
30+
.react-datepicker__navigation--next {
31+
border-left-color: #cbd5e0;
32+
33+
&:hover {
34+
border-left-color: #a0aec0;
35+
}
36+
}
37+
38+
.react-datepicker-wrapper,
39+
.react-datepicker__input-container {
40+
display: block;
41+
}
42+
43+
.react-datepicker__input-container input {
44+
padding-left: 1em;
45+
padding-right: 1em;
46+
color: darkslategrey;
47+
}
48+
49+
.react-datepicker__header {
50+
border-radius: 0;
51+
background: #f7fafc;
52+
}
53+
54+
.react-datepicker,
55+
.react-datepicker__header,
56+
.react-datepicker__time-container {
57+
border-color: #e2e8f0;
58+
}
59+
60+
.react-datepicker__current-month,
61+
.react-datepicker-time__header,
62+
.react-datepicker-year-header {
63+
font-size: inherit;
64+
font-weight: 600;
65+
}
66+
67+
.react-datepicker__time-container
68+
.react-datepicker__time
69+
.react-datepicker__time-box
70+
ul.react-datepicker__time-list
71+
li.react-datepicker__time-list-item {
72+
margin: 0 1px 0 0;
73+
height: auto;
74+
padding: 7px 10px;
75+
76+
&:hover {
77+
background: #edf2f7;
78+
}
79+
}
80+
81+
.react-datepicker__day:hover {
82+
background: #edf2f7;
83+
}
84+
85+
.react-datepicker__day--selected,
86+
.react-datepicker__day--in-selecting-range,
87+
.react-datepicker__day--in-range,
88+
.react-datepicker__month-text--selected,
89+
.react-datepicker__month-text--in-selecting-range,
90+
.react-datepicker__month-text--in-range,
91+
.react-datepicker__time-container
92+
.react-datepicker__time
93+
.react-datepicker__time-box
94+
ul.react-datepicker__time-list
95+
li.react-datepicker__time-list-item--selected {
96+
background: #3182ce;
97+
font-weight: normal;
98+
99+
&:hover {
100+
background: #2a69ac;
101+
}
102+
}

0 commit comments

Comments
 (0)