@ltht-react/input 2.0.189 → 2.0.191

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/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # Input
2
-
3
- <!-- STORY -->
4
-
5
- ### Import
6
-
7
- ```js
8
- import Input from '@ltht-react/input'
9
- ```
10
-
11
- ### Usage
12
-
13
- ```jsx
14
- <Input />
15
- ```
1
+ # Input
2
+
3
+ <!-- STORY -->
4
+
5
+ ### Import
6
+
7
+ ```js
8
+ import Input from '@ltht-react/input'
9
+ ```
10
+
11
+ ### Usage
12
+
13
+ ```jsx
14
+ <Input />
15
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ltht-react/input",
3
- "version": "2.0.189",
3
+ "version": "2.0.191",
4
4
  "description": "ltht-react styled Input component.",
5
5
  "author": "LTHT",
6
6
  "homepage": "",
@@ -28,11 +28,11 @@
28
28
  "dependencies": {
29
29
  "@emotion/react": "^11.0.0",
30
30
  "@emotion/styled": "^11.0.0",
31
- "@ltht-react/button": "^2.0.189",
32
- "@ltht-react/icon": "^2.0.189",
33
- "@ltht-react/styles": "^2.0.189",
34
- "@ltht-react/types": "^2.0.189",
35
- "@ltht-react/utils": "^2.0.189",
31
+ "@ltht-react/button": "^2.0.191",
32
+ "@ltht-react/icon": "^2.0.191",
33
+ "@ltht-react/styles": "^2.0.191",
34
+ "@ltht-react/types": "^2.0.191",
35
+ "@ltht-react/utils": "^2.0.191",
36
36
  "@popperjs/core": "^2.11.5",
37
37
  "date-fns": "^3.6.0",
38
38
  "focus-trap-react": "^9.0.2",
@@ -41,5 +41,5 @@
41
41
  "react-day-picker": "^8.9.1",
42
42
  "react-popper": "^2.3.0"
43
43
  },
44
- "gitHead": "ef1aa76019b62345209fce83df6f93c51024ee55"
44
+ "gitHead": "c5113953a19f4ed9ae82b545f073b5feb7d5a20b"
45
45
  }
@@ -1,92 +1,92 @@
1
- import { FC, HTMLAttributes, InputHTMLAttributes } from 'react'
2
- import styled from '@emotion/styled'
3
- import { BADGE_COLOURS, INPUT_COLOURS } from '@ltht-react/styles'
4
- import { css } from '@emotion/react'
5
-
6
- const StyledCheckbox = styled.div<ConditionalStyles>`
7
- display: flex;
8
- align-items: center;
9
- ${(props) =>
10
- props.checked &&
11
- css`
12
- background-color: ${INPUT_COLOURS.RADIO_SELECTED};
13
- `}
14
- `
15
-
16
- const StyledInput = styled.input`
17
- appearance: none;
18
- height: 1.2em;
19
- margin: 0;
20
- margin-right: 0.5em;
21
- position: relative;
22
- width: 1em;
23
-
24
- &:before {
25
- border: solid 1px grey;
26
- border-radius: 3px;
27
- content: '';
28
- display: inline-block;
29
- height: 1em;
30
- width: 1em;
31
- }
32
-
33
- &:checked:before {
34
- background-color: ${BADGE_COLOURS.PRIMARY};
35
- content: '';
36
- color: white;
37
- }
38
-
39
- &:checked:after {
40
- color: white;
41
- content: '\\2714';
42
- font-size: 0.8em;
43
- height: 1em;
44
- left: 0.25em;
45
- position: absolute;
46
- top: 0;
47
- width: 1em;
48
- }
49
- `
50
-
51
- const StyledLabel = styled.label`
52
- display: inline-block;
53
- margin-bottom: 0;
54
- `
55
-
56
- const Checkbox: FC<Props> = ({
57
- id,
58
- checked = false,
59
- onChange,
60
- children,
61
- name,
62
- parentDivAttributes = {},
63
- labelAttributes = {},
64
- ...rest
65
- }) => (
66
- <StyledCheckbox checked={checked} {...parentDivAttributes}>
67
- <StyledInput
68
- id={id}
69
- onChange={onChange}
70
- type="checkbox"
71
- checked={checked}
72
- aria-checked={checked}
73
- role="checkbox"
74
- name={name}
75
- {...rest}
76
- />
77
- <StyledLabel htmlFor={id} {...labelAttributes}>
78
- {children}
79
- </StyledLabel>
80
- </StyledCheckbox>
81
- )
82
-
83
- interface ConditionalStyles extends InputHTMLAttributes<HTMLInputElement> {
84
- checked: boolean
85
- }
86
- interface Props extends InputHTMLAttributes<HTMLInputElement> {
87
- children: React.ReactNode
88
- parentDivAttributes?: HTMLAttributes<HTMLDivElement>
89
- labelAttributes?: HTMLAttributes<HTMLLabelElement>
90
- }
91
-
92
- export default Checkbox
1
+ import { FC, HTMLAttributes, InputHTMLAttributes } from 'react'
2
+ import styled from '@emotion/styled'
3
+ import { BADGE_COLOURS, INPUT_COLOURS } from '@ltht-react/styles'
4
+ import { css } from '@emotion/react'
5
+
6
+ const StyledCheckbox = styled.div<ConditionalStyles>`
7
+ display: flex;
8
+ align-items: center;
9
+ ${(props) =>
10
+ props.checked &&
11
+ css`
12
+ background-color: ${INPUT_COLOURS.RADIO_SELECTED};
13
+ `}
14
+ `
15
+
16
+ const StyledInput = styled.input`
17
+ appearance: none;
18
+ height: 1.2em;
19
+ margin: 0;
20
+ margin-right: 0.5em;
21
+ position: relative;
22
+ width: 1em;
23
+
24
+ &:before {
25
+ border: solid 1px grey;
26
+ border-radius: 3px;
27
+ content: '';
28
+ display: inline-block;
29
+ height: 1em;
30
+ width: 1em;
31
+ }
32
+
33
+ &:checked:before {
34
+ background-color: ${BADGE_COLOURS.PRIMARY};
35
+ content: '';
36
+ color: white;
37
+ }
38
+
39
+ &:checked:after {
40
+ color: white;
41
+ content: '\\2714';
42
+ font-size: 0.8em;
43
+ height: 1em;
44
+ left: 0.25em;
45
+ position: absolute;
46
+ top: 0;
47
+ width: 1em;
48
+ }
49
+ `
50
+
51
+ const StyledLabel = styled.label`
52
+ display: inline-block;
53
+ margin-bottom: 0;
54
+ `
55
+
56
+ const Checkbox: FC<Props> = ({
57
+ id,
58
+ checked = false,
59
+ onChange,
60
+ children,
61
+ name,
62
+ parentDivAttributes = {},
63
+ labelAttributes = {},
64
+ ...rest
65
+ }) => (
66
+ <StyledCheckbox checked={checked} {...parentDivAttributes}>
67
+ <StyledInput
68
+ id={id}
69
+ onChange={onChange}
70
+ type="checkbox"
71
+ checked={checked}
72
+ aria-checked={checked}
73
+ role="checkbox"
74
+ name={name}
75
+ {...rest}
76
+ />
77
+ <StyledLabel htmlFor={id} {...labelAttributes}>
78
+ {children}
79
+ </StyledLabel>
80
+ </StyledCheckbox>
81
+ )
82
+
83
+ interface ConditionalStyles extends InputHTMLAttributes<HTMLInputElement> {
84
+ checked: boolean
85
+ }
86
+ interface Props extends InputHTMLAttributes<HTMLInputElement> {
87
+ children: React.ReactNode
88
+ parentDivAttributes?: HTMLAttributes<HTMLDivElement>
89
+ labelAttributes?: HTMLAttributes<HTMLLabelElement>
90
+ }
91
+
92
+ export default Checkbox
@@ -1,229 +1,229 @@
1
- import { ChangeEventHandler, FC, HTMLAttributes, MouseEventHandler, useRef, useState } from 'react'
2
- import styled from '@emotion/styled'
3
- import { DayPicker, SelectSingleEventHandler, DateBefore, Matcher, DateAfter } from 'react-day-picker'
4
- import { BTN_COLOURS, TEXT_COLOURS, TRANSLUCENT_DARK_BLUE } from '@ltht-react/styles'
5
- import { Button } from '@ltht-react/button'
6
- import { usePopper } from 'react-popper'
7
- import { format, isValid, parse } from 'date-fns'
8
- import FocusTrap from 'focus-trap-react'
9
- import Icon from '@ltht-react/icon'
10
-
11
- const StyledDialogSheet = styled.div`
12
- z-index: 1;
13
- background: white;
14
- border-radius: 4px;
15
- box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.04), 0px 4px 5px rgba(0, 0, 0, 0.06), 0px 2px 4px -1px rgba(0, 0, 0, 0.09);
16
- `
17
-
18
- const DayPickerLabel = styled.small`
19
- color: ${TEXT_COLOURS.SECONDARY.LIGHTER25};
20
- `
21
-
22
- const DayPickerInput = styled.input`
23
- :focus-visible {
24
- outline-color: ${BTN_COLOURS.PRIMARY.VALUE};
25
- outline-style: auto;
26
- outline-width: 1px;
27
- }
28
- `
29
-
30
- const InputContainer = styled.div<InputProps>`
31
- display: flex;
32
- margin-right: ${({ showIcon }) => (showIcon ? '0rem;' : '2rem;')};
33
- height: 1.5rem;
34
- `
35
-
36
- const StyledButton = styled(Button)`
37
- position: relative;
38
- right: 2rem;
39
- width: 2rem !important;
40
- `
41
-
42
- const StyledDayPicker = styled(DayPicker)`
43
- button.rdp-button:hover:not([aria-disabled='true']) {
44
- background-color: ${TRANSLUCENT_DARK_BLUE};
45
- }
46
-
47
- button.rdp-day_selected: not([aria-disabled= 'true' ]), button.rdp-day_selected:not([aria-disabled='true']),
48
- button.rdp-day_selected:focus:not([aria-disabled='true']),
49
- button.rdp-day_selected:active:not([aria-disabled='true']),
50
- button.rdp-day_selected:hover:not([aria-disabled='true']) {
51
- color: white;
52
- background-color: ${BTN_COLOURS.PRIMARY.VALUE};
53
- }
54
-
55
- button.rdp-button:focus, button.rdp-button:active {
56
- border-color: ${BTN_COLOURS.PRIMARY.VALUE};
57
- }
58
- `
59
-
60
- const Daypicker: FC<DaypickerProps> = ({
61
- initialDate,
62
- pickerOpen,
63
- showIcon,
64
- dayFormat,
65
- label,
66
- minDate,
67
- maxDate,
68
- navigationNumberOfMonths = 1,
69
- changeHandler,
70
- buttonHandler,
71
- }) => {
72
- const [selected, setSelected] = useState<Date | undefined>(initialDate)
73
- const [inputValue, setInputValue] = useState<string>(format(initialDate ?? new Date(), dayFormat))
74
- const [isPopperOpen, setIsPopperOpen] = useState(pickerOpen ?? false)
75
-
76
- const disabledDays: Matcher[] = []
77
-
78
- if (minDate) {
79
- const disabledBefore: DateBefore = {
80
- before: minDate,
81
- }
82
-
83
- disabledDays.push(disabledBefore)
84
- }
85
-
86
- if (maxDate) {
87
- const disabledAfter: DateAfter = {
88
- after: maxDate,
89
- }
90
-
91
- disabledDays.push(disabledAfter)
92
- }
93
-
94
- const popperRef = useRef<HTMLDivElement>(null)
95
- const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null)
96
-
97
- const popper = usePopper(popperRef.current, popperElement, {
98
- placement: 'bottom-start',
99
- })
100
-
101
- const closePopper = () => {
102
- setIsPopperOpen(false)
103
- }
104
-
105
- const selectDate = (date: Date | undefined) => {
106
- setSelected(date)
107
- changeHandler && changeHandler(date)
108
- }
109
-
110
- const handleInputChange: ChangeEventHandler<HTMLInputElement> = (e) => {
111
- setInputValue(e.currentTarget.value)
112
- const date = parse(e.currentTarget.value, dayFormat, new Date())
113
- if (isValid(date)) {
114
- selectDate(date)
115
- } else {
116
- selectDate(undefined)
117
- }
118
- }
119
-
120
- const handleSelect: SelectSingleEventHandler = (_day, selectedDay, _activeModifiers, _e) => {
121
- if (_activeModifiers.disabled) {
122
- return
123
- }
124
- selectDate(selectedDay)
125
- if (selectedDay) {
126
- setInputValue(format(selectedDay, dayFormat))
127
- closePopper()
128
- } else {
129
- setInputValue('')
130
- }
131
- }
132
-
133
- const onInputClick: MouseEventHandler<HTMLInputElement> = () => {
134
- setIsPopperOpen(true)
135
- }
136
-
137
- const onButtonClick: MouseEventHandler<HTMLButtonElement> = () => {
138
- const popperOpen = !isPopperOpen
139
- setIsPopperOpen(popperOpen)
140
- buttonHandler && buttonHandler(popperOpen)
141
- }
142
-
143
- return (
144
- <FocusTrap
145
- active={isPopperOpen}
146
- focusTrapOptions={{
147
- tabbableOptions: {
148
- displayCheck: 'none',
149
- },
150
- initialFocus: false,
151
- allowOutsideClick: false,
152
- clickOutsideDeactivates: true,
153
- onDeactivate: closePopper,
154
- }}
155
- >
156
- <div>
157
- {label && <DayPickerLabel>{label}</DayPickerLabel>}
158
- <InputContainer ref={popperRef} showIcon={showIcon}>
159
- <DayPickerInput
160
- type="text"
161
- readOnly
162
- placeholder={format(initialDate ?? new Date(), dayFormat)}
163
- value={inputValue}
164
- onChange={handleInputChange}
165
- onClick={!showIcon ? onInputClick : undefined}
166
- />
167
- {showIcon && (
168
- <StyledButton
169
- type="button"
170
- icon={<Icon type="calendar" size="medium" />}
171
- iconPlacement="center"
172
- onClick={onButtonClick}
173
- />
174
- )}
175
- </InputContainer>
176
- {isPopperOpen && (
177
- <StyledDialogSheet
178
- tabIndex={-1}
179
- style={popper.styles.popper}
180
- {...popper.attributes.popper}
181
- ref={setPopperElement}
182
- role="dialog"
183
- >
184
- <StyledDayPicker
185
- initialFocus={isPopperOpen}
186
- mode="single"
187
- defaultMonth={selected}
188
- selected={selected}
189
- onSelect={handleSelect}
190
- fromMonth={minDate}
191
- toMonth={maxDate}
192
- disabled={disabledDays}
193
- numberOfMonths={navigationNumberOfMonths}
194
- pagedNavigation
195
- />
196
- </StyledDialogSheet>
197
- )}
198
- </div>
199
- </FocusTrap>
200
- )
201
- }
202
-
203
- interface InputProps extends HTMLAttributes<HTMLDivElement> {
204
- showIcon: boolean
205
- }
206
-
207
- export interface DaypickerProps extends HTMLAttributes<HTMLDivElement> {
208
- initialDate?: Date
209
- pickerOpen?: boolean | undefined
210
- showIcon: boolean
211
- dayFormat: string
212
- label?: string
213
- minDate?: Date | undefined
214
- maxDate?: Date | undefined
215
- /**
216
- * The number of displayed months in navigation. Defaults to `1`.
217
- */
218
- navigationNumberOfMonths?: number | undefined
219
- /**
220
- * Executes whenever a day is selected from picker
221
- */
222
- changeHandler?: (day: Date | undefined) => void | undefined
223
- /**
224
- * Executes when the button icon clicked
225
- */
226
- buttonHandler?: (datepickerOpen: boolean) => void | undefined
227
- }
228
-
229
- export default Daypicker
1
+ import { ChangeEventHandler, FC, HTMLAttributes, MouseEventHandler, useRef, useState } from 'react'
2
+ import styled from '@emotion/styled'
3
+ import { DayPicker, SelectSingleEventHandler, DateBefore, Matcher, DateAfter } from 'react-day-picker'
4
+ import { BTN_COLOURS, TEXT_COLOURS, TRANSLUCENT_DARK_BLUE } from '@ltht-react/styles'
5
+ import { Button } from '@ltht-react/button'
6
+ import { usePopper } from 'react-popper'
7
+ import { format, isValid, parse } from 'date-fns'
8
+ import FocusTrap from 'focus-trap-react'
9
+ import Icon from '@ltht-react/icon'
10
+
11
+ const StyledDialogSheet = styled.div`
12
+ z-index: 1;
13
+ background: white;
14
+ border-radius: 4px;
15
+ box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.04), 0px 4px 5px rgba(0, 0, 0, 0.06), 0px 2px 4px -1px rgba(0, 0, 0, 0.09);
16
+ `
17
+
18
+ const DayPickerLabel = styled.small`
19
+ color: ${TEXT_COLOURS.SECONDARY.LIGHTER25};
20
+ `
21
+
22
+ const DayPickerInput = styled.input`
23
+ :focus-visible {
24
+ outline-color: ${BTN_COLOURS.PRIMARY.VALUE};
25
+ outline-style: auto;
26
+ outline-width: 1px;
27
+ }
28
+ `
29
+
30
+ const InputContainer = styled.div<InputProps>`
31
+ display: flex;
32
+ margin-right: ${({ showIcon }) => (showIcon ? '0rem;' : '2rem;')};
33
+ height: 1.5rem;
34
+ `
35
+
36
+ const StyledButton = styled(Button)`
37
+ position: relative;
38
+ right: 2rem;
39
+ width: 2rem !important;
40
+ `
41
+
42
+ const StyledDayPicker = styled(DayPicker)`
43
+ button.rdp-button:hover:not([aria-disabled='true']) {
44
+ background-color: ${TRANSLUCENT_DARK_BLUE};
45
+ }
46
+
47
+ button.rdp-day_selected: not([aria-disabled= 'true' ]), button.rdp-day_selected:not([aria-disabled='true']),
48
+ button.rdp-day_selected:focus:not([aria-disabled='true']),
49
+ button.rdp-day_selected:active:not([aria-disabled='true']),
50
+ button.rdp-day_selected:hover:not([aria-disabled='true']) {
51
+ color: white;
52
+ background-color: ${BTN_COLOURS.PRIMARY.VALUE};
53
+ }
54
+
55
+ button.rdp-button:focus, button.rdp-button:active {
56
+ border-color: ${BTN_COLOURS.PRIMARY.VALUE};
57
+ }
58
+ `
59
+
60
+ const Daypicker: FC<DaypickerProps> = ({
61
+ initialDate,
62
+ pickerOpen,
63
+ showIcon,
64
+ dayFormat,
65
+ label,
66
+ minDate,
67
+ maxDate,
68
+ navigationNumberOfMonths = 1,
69
+ changeHandler,
70
+ buttonHandler,
71
+ }) => {
72
+ const [selected, setSelected] = useState<Date | undefined>(initialDate)
73
+ const [inputValue, setInputValue] = useState<string>(format(initialDate ?? new Date(), dayFormat))
74
+ const [isPopperOpen, setIsPopperOpen] = useState(pickerOpen ?? false)
75
+
76
+ const disabledDays: Matcher[] = []
77
+
78
+ if (minDate) {
79
+ const disabledBefore: DateBefore = {
80
+ before: minDate,
81
+ }
82
+
83
+ disabledDays.push(disabledBefore)
84
+ }
85
+
86
+ if (maxDate) {
87
+ const disabledAfter: DateAfter = {
88
+ after: maxDate,
89
+ }
90
+
91
+ disabledDays.push(disabledAfter)
92
+ }
93
+
94
+ const popperRef = useRef<HTMLDivElement>(null)
95
+ const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null)
96
+
97
+ const popper = usePopper(popperRef.current, popperElement, {
98
+ placement: 'bottom-start',
99
+ })
100
+
101
+ const closePopper = () => {
102
+ setIsPopperOpen(false)
103
+ }
104
+
105
+ const selectDate = (date: Date | undefined) => {
106
+ setSelected(date)
107
+ changeHandler && changeHandler(date)
108
+ }
109
+
110
+ const handleInputChange: ChangeEventHandler<HTMLInputElement> = (e) => {
111
+ setInputValue(e.currentTarget.value)
112
+ const date = parse(e.currentTarget.value, dayFormat, new Date())
113
+ if (isValid(date)) {
114
+ selectDate(date)
115
+ } else {
116
+ selectDate(undefined)
117
+ }
118
+ }
119
+
120
+ const handleSelect: SelectSingleEventHandler = (_day, selectedDay, _activeModifiers, _e) => {
121
+ if (_activeModifiers.disabled) {
122
+ return
123
+ }
124
+ selectDate(selectedDay)
125
+ if (selectedDay) {
126
+ setInputValue(format(selectedDay, dayFormat))
127
+ closePopper()
128
+ } else {
129
+ setInputValue('')
130
+ }
131
+ }
132
+
133
+ const onInputClick: MouseEventHandler<HTMLInputElement> = () => {
134
+ setIsPopperOpen(true)
135
+ }
136
+
137
+ const onButtonClick: MouseEventHandler<HTMLButtonElement> = () => {
138
+ const popperOpen = !isPopperOpen
139
+ setIsPopperOpen(popperOpen)
140
+ buttonHandler && buttonHandler(popperOpen)
141
+ }
142
+
143
+ return (
144
+ <FocusTrap
145
+ active={isPopperOpen}
146
+ focusTrapOptions={{
147
+ tabbableOptions: {
148
+ displayCheck: 'none',
149
+ },
150
+ initialFocus: false,
151
+ allowOutsideClick: false,
152
+ clickOutsideDeactivates: true,
153
+ onDeactivate: closePopper,
154
+ }}
155
+ >
156
+ <div>
157
+ {label && <DayPickerLabel>{label}</DayPickerLabel>}
158
+ <InputContainer ref={popperRef} showIcon={showIcon}>
159
+ <DayPickerInput
160
+ type="text"
161
+ readOnly
162
+ placeholder={format(initialDate ?? new Date(), dayFormat)}
163
+ value={inputValue}
164
+ onChange={handleInputChange}
165
+ onClick={!showIcon ? onInputClick : undefined}
166
+ />
167
+ {showIcon && (
168
+ <StyledButton
169
+ type="button"
170
+ icon={<Icon type="calendar" size="medium" />}
171
+ iconPlacement="center"
172
+ onClick={onButtonClick}
173
+ />
174
+ )}
175
+ </InputContainer>
176
+ {isPopperOpen && (
177
+ <StyledDialogSheet
178
+ tabIndex={-1}
179
+ style={popper.styles.popper}
180
+ {...popper.attributes.popper}
181
+ ref={setPopperElement}
182
+ role="dialog"
183
+ >
184
+ <StyledDayPicker
185
+ initialFocus={isPopperOpen}
186
+ mode="single"
187
+ defaultMonth={selected}
188
+ selected={selected}
189
+ onSelect={handleSelect}
190
+ fromMonth={minDate}
191
+ toMonth={maxDate}
192
+ disabled={disabledDays}
193
+ numberOfMonths={navigationNumberOfMonths}
194
+ pagedNavigation
195
+ />
196
+ </StyledDialogSheet>
197
+ )}
198
+ </div>
199
+ </FocusTrap>
200
+ )
201
+ }
202
+
203
+ interface InputProps extends HTMLAttributes<HTMLDivElement> {
204
+ showIcon: boolean
205
+ }
206
+
207
+ export interface DaypickerProps extends HTMLAttributes<HTMLDivElement> {
208
+ initialDate?: Date
209
+ pickerOpen?: boolean | undefined
210
+ showIcon: boolean
211
+ dayFormat: string
212
+ label?: string
213
+ minDate?: Date | undefined
214
+ maxDate?: Date | undefined
215
+ /**
216
+ * The number of displayed months in navigation. Defaults to `1`.
217
+ */
218
+ navigationNumberOfMonths?: number | undefined
219
+ /**
220
+ * Executes whenever a day is selected from picker
221
+ */
222
+ changeHandler?: (day: Date | undefined) => void | undefined
223
+ /**
224
+ * Executes when the button icon clicked
225
+ */
226
+ buttonHandler?: (datepickerOpen: boolean) => void | undefined
227
+ }
228
+
229
+ export default Daypicker
@@ -1,5 +1,5 @@
1
- export { default as RadioButton } from './radio'
2
- export { default as Checkbox } from './checkbox'
3
- export { default as TextInput } from './text'
4
- export { default as Daypicker, DaypickerProps } from './daypicker'
5
- export { default as Toggle } from './toggle'
1
+ export { default as RadioButton } from './radio'
2
+ export { default as Checkbox } from './checkbox'
3
+ export { default as TextInput } from './text'
4
+ export { default as Daypicker, DaypickerProps } from './daypicker'
5
+ export { default as Toggle } from './toggle'
@@ -1,47 +1,47 @@
1
- import { ChangeEvent, FC, HTMLAttributes } from 'react'
2
- import styled from '@emotion/styled'
3
- import { css, SerializedStyles } from '@emotion/react'
4
- import { INPUT_COLOURS } from '@ltht-react/styles'
5
-
6
- const StyledRadioButton = styled.div<StyledRadioButtonProps>`
7
- padding-left: 1.25rem;
8
-
9
- ${({ checked }): ConditionalStyles =>
10
- checked &&
11
- css`
12
- background-color: ${INPUT_COLOURS.RADIO_SELECTED};
13
- `}
14
- `
15
-
16
- const StyledInput = styled.input`
17
- position: absolute;
18
- margin-top: 0.15rem;
19
- margin-left: -1.25rem;
20
- `
21
-
22
- const StyledLabel = styled.label`
23
- display: inline-block;
24
- margin-bottom: 0;
25
- `
26
-
27
- const RadioButton: FC<Props> = ({ id, value, checked = false, label, changeHandler, ...rest }) => (
28
- <StyledRadioButton checked={checked} {...rest}>
29
- <StyledInput id={id} onChange={changeHandler} value={value} type="radio" checked={checked} />
30
- <StyledLabel htmlFor={id}>{label}</StyledLabel>
31
- </StyledRadioButton>
32
- )
33
-
34
- type ConditionalStyles = SerializedStyles | false
35
-
36
- interface StyledRadioButtonProps {
37
- checked: boolean
38
- }
39
- interface Props extends HTMLAttributes<HTMLDivElement> {
40
- id: string
41
- value: string
42
- checked?: boolean
43
- label: string
44
- changeHandler(e: ChangeEvent<HTMLInputElement>): void
45
- }
46
-
47
- export default RadioButton
1
+ import { ChangeEvent, FC, HTMLAttributes } from 'react'
2
+ import styled from '@emotion/styled'
3
+ import { css, SerializedStyles } from '@emotion/react'
4
+ import { INPUT_COLOURS } from '@ltht-react/styles'
5
+
6
+ const StyledRadioButton = styled.div<StyledRadioButtonProps>`
7
+ padding-left: 1.25rem;
8
+
9
+ ${({ checked }): ConditionalStyles =>
10
+ checked &&
11
+ css`
12
+ background-color: ${INPUT_COLOURS.RADIO_SELECTED};
13
+ `}
14
+ `
15
+
16
+ const StyledInput = styled.input`
17
+ position: absolute;
18
+ margin-top: 0.15rem;
19
+ margin-left: -1.25rem;
20
+ `
21
+
22
+ const StyledLabel = styled.label`
23
+ display: inline-block;
24
+ margin-bottom: 0;
25
+ `
26
+
27
+ const RadioButton: FC<Props> = ({ id, value, checked = false, label, changeHandler, ...rest }) => (
28
+ <StyledRadioButton checked={checked} {...rest}>
29
+ <StyledInput id={id} onChange={changeHandler} value={value} type="radio" checked={checked} />
30
+ <StyledLabel htmlFor={id}>{label}</StyledLabel>
31
+ </StyledRadioButton>
32
+ )
33
+
34
+ type ConditionalStyles = SerializedStyles | false
35
+
36
+ interface StyledRadioButtonProps {
37
+ checked: boolean
38
+ }
39
+ interface Props extends HTMLAttributes<HTMLDivElement> {
40
+ id: string
41
+ value: string
42
+ checked?: boolean
43
+ label: string
44
+ changeHandler(e: ChangeEvent<HTMLInputElement>): void
45
+ }
46
+
47
+ export default RadioButton
@@ -1,57 +1,57 @@
1
- import { FC, InputHTMLAttributes } from 'react'
2
- import styled from '@emotion/styled'
3
- import { DESKTOP_MINIMUM_MEDIA_QUERY, inputBaseStyles } from '@ltht-react/styles'
4
- import Icon, { IconProps } from '@ltht-react/icon'
5
-
6
- const TextInputContainer = styled.div`
7
- width: 100%;
8
- display: inline-block;
9
- position: relative;
10
-
11
- ${DESKTOP_MINIMUM_MEDIA_QUERY} {
12
- width: auto;
13
- }
14
- `
15
-
16
- const StyledTextInput: FC<IStyledTextInputProps> = styled.input`
17
- width: 100%;
18
- ${inputBaseStyles}
19
- padding: 0.5rem 1rem 0.5rem 1.75rem;
20
- padding-left: ${({ hasIcon }: IStyledTextInputProps) => (hasIcon ? '1.75rem' : '0.5rem')};
21
- &::placeholder {
22
- color: #98a4ad;
23
- }
24
-
25
- ${DESKTOP_MINIMUM_MEDIA_QUERY} {
26
- width: auto;
27
- }
28
- `
29
-
30
- const StyledIcon = styled(Icon)`
31
- position: absolute;
32
- left: 8px;
33
- top: 50%;
34
- transform: translateY(-50%);
35
- color: #98a4ad;
36
-
37
- ${DESKTOP_MINIMUM_MEDIA_QUERY} {
38
- width: auto;
39
- }
40
- `
41
-
42
- const TextInput: FC<ITextInputProps> = ({ placeholder, icon, ...rest }) => (
43
- <TextInputContainer>
44
- {icon && <StyledIcon {...icon} />}
45
- <StyledTextInput type="text" placeholder={placeholder} {...rest} hasIcon={icon !== undefined} />
46
- </TextInputContainer>
47
- )
48
-
49
- interface ITextInputProps extends InputHTMLAttributes<HTMLInputElement> {
50
- icon?: IconProps
51
- }
52
-
53
- interface IStyledTextInputProps extends ITextInputProps {
54
- hasIcon: boolean
55
- }
56
-
57
- export default TextInput
1
+ import { FC, InputHTMLAttributes } from 'react'
2
+ import styled from '@emotion/styled'
3
+ import { DESKTOP_MINIMUM_MEDIA_QUERY, inputBaseStyles } from '@ltht-react/styles'
4
+ import Icon, { IconProps } from '@ltht-react/icon'
5
+
6
+ const TextInputContainer = styled.div`
7
+ width: 100%;
8
+ display: inline-block;
9
+ position: relative;
10
+
11
+ ${DESKTOP_MINIMUM_MEDIA_QUERY} {
12
+ width: auto;
13
+ }
14
+ `
15
+
16
+ const StyledTextInput: FC<IStyledTextInputProps> = styled.input`
17
+ width: 100%;
18
+ ${inputBaseStyles}
19
+ padding: 0.5rem 1rem 0.5rem 1.75rem;
20
+ padding-left: ${({ hasIcon }: IStyledTextInputProps) => (hasIcon ? '1.75rem' : '0.5rem')};
21
+ &::placeholder {
22
+ color: #98a4ad;
23
+ }
24
+
25
+ ${DESKTOP_MINIMUM_MEDIA_QUERY} {
26
+ width: auto;
27
+ }
28
+ `
29
+
30
+ const StyledIcon = styled(Icon)`
31
+ position: absolute;
32
+ left: 8px;
33
+ top: 50%;
34
+ transform: translateY(-50%);
35
+ color: #98a4ad;
36
+
37
+ ${DESKTOP_MINIMUM_MEDIA_QUERY} {
38
+ width: auto;
39
+ }
40
+ `
41
+
42
+ const TextInput: FC<ITextInputProps> = ({ placeholder, icon, ...rest }) => (
43
+ <TextInputContainer>
44
+ {icon && <StyledIcon {...icon} />}
45
+ <StyledTextInput type="text" placeholder={placeholder} {...rest} hasIcon={icon !== undefined} />
46
+ </TextInputContainer>
47
+ )
48
+
49
+ interface ITextInputProps extends InputHTMLAttributes<HTMLInputElement> {
50
+ icon?: IconProps
51
+ }
52
+
53
+ interface IStyledTextInputProps extends ITextInputProps {
54
+ hasIcon: boolean
55
+ }
56
+
57
+ export default TextInput
package/src/index.tsx CHANGED
@@ -1,2 +1,2 @@
1
- export * from './atoms'
2
- export * from './molecules'
1
+ export * from './atoms'
2
+ export * from './molecules'
@@ -1,89 +1,89 @@
1
- import styled from '@emotion/styled'
2
- import { FC, HTMLAttributes, useState } from 'react'
3
- import { Daypicker, DaypickerProps } from '../atoms'
4
-
5
- const RangeContainer = styled.div`
6
- display: flex;
7
- `
8
-
9
- const PickerContainer = styled.div`
10
- flex: 1;
11
- `
12
-
13
- const DaypickerRange: FC<Props> = ({ fromProps, toProps }) => {
14
- if (fromProps.minDate && toProps.maxDate && fromProps.minDate > toProps.maxDate) {
15
- throw new Error(
16
- `Cannot initialise DaypickerRange where the minDate: ${fromProps.minDate?.toDateString()} > maxDate: ${toProps.maxDate?.toDateString()} `
17
- )
18
- }
19
-
20
- const [toMinDate, setToMinDate] = useState(fromProps.minDate)
21
- const [fromMaxDate, setFromMaxDate] = useState(toProps.maxDate)
22
- const [fromPickerOpen, setFromPickerOpen] = useState(fromProps.pickerOpen ?? false)
23
- const [toPickerOpen, setToPickerOpen] = useState(toProps.pickerOpen ?? false)
24
-
25
- const fromChangeHandler = (date: Date | undefined) => {
26
- fromProps.changeHandler && fromProps.changeHandler(date)
27
- setToMinDate(date)
28
- }
29
-
30
- const toChangeHandler = (date: Date | undefined) => {
31
- toProps.changeHandler && toProps.changeHandler(date)
32
- setFromMaxDate(date)
33
- }
34
-
35
- const toButtonHandler = (toPickerOpen: boolean) => {
36
- if (toPickerOpen) {
37
- setFromPickerOpen(false)
38
- }
39
- }
40
-
41
- const fromButtonHandler = (fromPickerOpen: boolean) => {
42
- if (fromPickerOpen) {
43
- setToPickerOpen(false)
44
- }
45
- }
46
-
47
- return (
48
- <RangeContainer>
49
- <PickerContainer>
50
- <Daypicker
51
- initialDate={fromProps.initialDate}
52
- showIcon={fromProps.showIcon}
53
- pickerOpen={fromPickerOpen}
54
- dayFormat={fromProps.dayFormat}
55
- label={fromProps.label}
56
- minDate={fromProps.minDate}
57
- maxDate={fromMaxDate}
58
- navigationNumberOfMonths={fromProps.navigationNumberOfMonths}
59
- changeHandler={fromChangeHandler}
60
- buttonHandler={fromButtonHandler}
61
- />
62
- </PickerContainer>
63
- <PickerContainer>
64
- <Daypicker
65
- initialDate={toProps.initialDate}
66
- pickerOpen={toPickerOpen}
67
- showIcon={toProps.showIcon}
68
- dayFormat={toProps.dayFormat}
69
- label={toProps.label}
70
- minDate={toMinDate}
71
- maxDate={toProps.maxDate}
72
- navigationNumberOfMonths={toProps.navigationNumberOfMonths}
73
- changeHandler={toChangeHandler}
74
- buttonHandler={toButtonHandler}
75
- />
76
- </PickerContainer>
77
- </RangeContainer>
78
- )
79
- }
80
-
81
- export type fromDaypickerRangeProps = Omit<DaypickerProps, 'maxDate'>
82
- export type toDaypickerRangeProps = Omit<DaypickerProps, 'minDate'>
83
-
84
- interface Props extends HTMLAttributes<HTMLDivElement> {
85
- fromProps: fromDaypickerRangeProps
86
- toProps: toDaypickerRangeProps
87
- }
88
-
89
- export default DaypickerRange
1
+ import styled from '@emotion/styled'
2
+ import { FC, HTMLAttributes, useState } from 'react'
3
+ import { Daypicker, DaypickerProps } from '../atoms'
4
+
5
+ const RangeContainer = styled.div`
6
+ display: flex;
7
+ `
8
+
9
+ const PickerContainer = styled.div`
10
+ flex: 1;
11
+ `
12
+
13
+ const DaypickerRange: FC<Props> = ({ fromProps, toProps }) => {
14
+ if (fromProps.minDate && toProps.maxDate && fromProps.minDate > toProps.maxDate) {
15
+ throw new Error(
16
+ `Cannot initialise DaypickerRange where the minDate: ${fromProps.minDate?.toDateString()} > maxDate: ${toProps.maxDate?.toDateString()} `
17
+ )
18
+ }
19
+
20
+ const [toMinDate, setToMinDate] = useState(fromProps.minDate)
21
+ const [fromMaxDate, setFromMaxDate] = useState(toProps.maxDate)
22
+ const [fromPickerOpen, setFromPickerOpen] = useState(fromProps.pickerOpen ?? false)
23
+ const [toPickerOpen, setToPickerOpen] = useState(toProps.pickerOpen ?? false)
24
+
25
+ const fromChangeHandler = (date: Date | undefined) => {
26
+ fromProps.changeHandler && fromProps.changeHandler(date)
27
+ setToMinDate(date)
28
+ }
29
+
30
+ const toChangeHandler = (date: Date | undefined) => {
31
+ toProps.changeHandler && toProps.changeHandler(date)
32
+ setFromMaxDate(date)
33
+ }
34
+
35
+ const toButtonHandler = (toPickerOpen: boolean) => {
36
+ if (toPickerOpen) {
37
+ setFromPickerOpen(false)
38
+ }
39
+ }
40
+
41
+ const fromButtonHandler = (fromPickerOpen: boolean) => {
42
+ if (fromPickerOpen) {
43
+ setToPickerOpen(false)
44
+ }
45
+ }
46
+
47
+ return (
48
+ <RangeContainer>
49
+ <PickerContainer>
50
+ <Daypicker
51
+ initialDate={fromProps.initialDate}
52
+ showIcon={fromProps.showIcon}
53
+ pickerOpen={fromPickerOpen}
54
+ dayFormat={fromProps.dayFormat}
55
+ label={fromProps.label}
56
+ minDate={fromProps.minDate}
57
+ maxDate={fromMaxDate}
58
+ navigationNumberOfMonths={fromProps.navigationNumberOfMonths}
59
+ changeHandler={fromChangeHandler}
60
+ buttonHandler={fromButtonHandler}
61
+ />
62
+ </PickerContainer>
63
+ <PickerContainer>
64
+ <Daypicker
65
+ initialDate={toProps.initialDate}
66
+ pickerOpen={toPickerOpen}
67
+ showIcon={toProps.showIcon}
68
+ dayFormat={toProps.dayFormat}
69
+ label={toProps.label}
70
+ minDate={toMinDate}
71
+ maxDate={toProps.maxDate}
72
+ navigationNumberOfMonths={toProps.navigationNumberOfMonths}
73
+ changeHandler={toChangeHandler}
74
+ buttonHandler={toButtonHandler}
75
+ />
76
+ </PickerContainer>
77
+ </RangeContainer>
78
+ )
79
+ }
80
+
81
+ export type fromDaypickerRangeProps = Omit<DaypickerProps, 'maxDate'>
82
+ export type toDaypickerRangeProps = Omit<DaypickerProps, 'minDate'>
83
+
84
+ interface Props extends HTMLAttributes<HTMLDivElement> {
85
+ fromProps: fromDaypickerRangeProps
86
+ toProps: toDaypickerRangeProps
87
+ }
88
+
89
+ export default DaypickerRange
@@ -1 +1 @@
1
- export { default as DaypickerRange, fromDaypickerRangeProps, toDaypickerRangeProps } from './daypicker-range'
1
+ export { default as DaypickerRange, fromDaypickerRangeProps, toDaypickerRangeProps } from './daypicker-range'