@telus-uds/components-web 2.7.0 → 2.8.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.
@@ -7,19 +7,21 @@ import SingleDatePicker from 'react-dates/lib/components/SingleDatePicker'
7
7
  import DayPickerSingleDateController from 'react-dates/lib/components/DayPickerSingleDateController'
8
8
  import {
9
9
  IconButton,
10
- InputSupports,
10
+ TextInput,
11
11
  selectSystemProps,
12
12
  useCopy,
13
13
  useViewport,
14
14
  useThemeTokens,
15
15
  applyTextStyles
16
16
  } from '@telus-uds/components-base'
17
+ import moment from 'moment'
17
18
  import CalendarContainer from './CalendarContainer'
18
19
  import dictionary from './dictionary'
19
20
  import { htmlAttrs } from '../utils'
20
21
 
21
22
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
22
-
23
+ const dateFormat = 'DD / MM / YYYY'
24
+ const dateFormatWithoutSpaces = 'DD/MM/YYYY'
23
25
  const getResponsiveDaySize = (inline = false, viewport = 'md') => {
24
26
  let responsiveDaySize
25
27
  if (viewport === 'xs') {
@@ -46,6 +48,11 @@ const MonthCenterContainer = styled.div({
46
48
  justifyContent: 'center'
47
49
  })
48
50
 
51
+ const DateInputWrapper = styled.div({
52
+ display: 'flex',
53
+ flexDirection: 'column'
54
+ })
55
+
49
56
  /**
50
57
  * Use DatePicker to select a date on a calendar.
51
58
  *
@@ -88,22 +95,49 @@ const DatePicker = forwardRef(
88
95
  },
89
96
  ref
90
97
  ) => {
91
- const [inputDate, setInputDate] = useState(date)
92
- const [isFocused, setIsFocused] = useState(false)
98
+ const [inputDate, setInputDate] = useState(date instanceof moment ? date : undefined)
99
+ const [inputText, setInputText] = useState(
100
+ date instanceof moment ? date.format(dateFormat) : ''
101
+ )
93
102
 
103
+ const [isFocused, setIsFocused] = useState(false)
104
+ const [isClickedInside, setIsClickedInside] = useState(false)
94
105
  const getCopy = useCopy({ dictionary, copy })
95
106
  const onFocusChange = ({ focused }) => {
96
- setIsFocused(focused)
107
+ if (!isClickedInside) {
108
+ setIsFocused(focused)
109
+ }
110
+ setIsClickedInside(false)
111
+ }
112
+ const handleFocus = () => {
113
+ setIsFocused(true)
114
+ }
115
+ const handleMouseDown = (event) => {
116
+ if (event.target.tagName === 'INPUT') {
117
+ setIsClickedInside(true)
118
+ setIsFocused(true)
119
+ } else {
120
+ event.stopPropagation()
121
+ }
97
122
  }
98
123
  const onChange = (value) => {
99
124
  setInputDate(value)
125
+ setInputText(value.format(dateFormat))
100
126
  if (onDateChange) onDateChange(value)
101
127
  }
128
+ const onChangeInput = (value) => {
129
+ if (moment(value.replace(/\s/g, ''), dateFormatWithoutSpaces, true).isValid()) {
130
+ setInputDate(moment(value, dateFormat))
131
+ if (onDateChange) onDateChange(moment(value, dateFormat))
132
+ setInputText(moment(value, dateFormatWithoutSpaces).format(dateFormat))
133
+ } else {
134
+ setInputText(value)
135
+ }
136
+ }
102
137
  const viewport = useViewport()
103
138
  const daySize = getResponsiveDaySize(inline, viewport)
104
139
  const circleSize = getResponsiveCircleSize(inline, viewport)
105
140
 
106
- const value = date ?? inputDate
107
141
  const HiddenInputFieldContainer = styled.div`
108
142
  height: ${(props) => props.height};
109
143
  width: ${(props) => props.width};
@@ -164,76 +198,27 @@ const DatePicker = forwardRef(
164
198
  calendarWeekFontTokens={calendarWeekFontTokens}
165
199
  defaultFontTokens={defaultFontTokens}
166
200
  >
167
- <InputSupports
168
- copy={copy}
169
- feedback={feedback}
170
- hint={hint}
171
- hintPosition={hintPosition}
172
- label={dictionary[copy]?.roleDescription ?? label}
173
- nativeID={id}
174
- tooltip={tooltip}
175
- validation={validation}
176
- >
177
- {inline ? (
178
- <>
179
- <HiddenInputFieldContainer
180
- height={hiddenInputFieldContainerHeight}
181
- width={hiddenInputFieldContainerWidth}
182
- >
183
- <input
184
- ref={ref}
185
- id={id}
186
- type="text"
187
- value={value?.format('YYYY-MM-DD') ?? ''}
188
- readOnly
189
- />
190
- </HiddenInputFieldContainer>
191
- <DayPickerSingleDateController
192
- date={value}
193
- onDateChange={onChange}
194
- focused={isFocused}
195
- onFocusChange={onFocusChange}
196
- numberOfMonths={1}
197
- hideKeyboardShortcutsPanel={true}
198
- keepOpenOnDateSelect={false}
199
- daySize={daySize}
200
- renderNavPrevButton={renderPrevButton}
201
- renderNavNextButton={renderNextButton}
202
- isOutsideRange={isDayDisabled}
203
- phrases={getCopy()}
204
- renderMonthElement={({ month }) => (
205
- <MonthCenterContainer>
206
- <div>
207
- {dictionary[copy]
208
- ? dictionary[copy].months[month.month()]
209
- : month.format('MMMM')}{' '}
210
- {month.year()}
211
- </div>
212
- </MonthCenterContainer>
213
- )}
214
- renderWeekHeaderElement={(day) => (
215
- <div>{dictionary[copy] ? dictionary[copy].weekDays[day] : day}</div>
216
- )}
217
- />
218
- </>
219
- ) : (
220
- <SingleDatePicker
221
- date={value}
201
+ {inline ? (
202
+ <>
203
+ <HiddenInputFieldContainer
204
+ height={hiddenInputFieldContainerHeight}
205
+ width={hiddenInputFieldContainerWidth}
206
+ >
207
+ <input ref={ref} id={id} type="text" value={inputText} readOnly />
208
+ </HiddenInputFieldContainer>
209
+ <DayPickerSingleDateController
210
+ date={inputDate}
222
211
  onDateChange={onChange}
223
212
  focused={isFocused}
224
213
  onFocusChange={onFocusChange}
225
214
  numberOfMonths={1}
226
215
  hideKeyboardShortcutsPanel={true}
227
- keepOpenOnDateSelect={true}
216
+ keepOpenOnDateSelect={false}
228
217
  daySize={daySize}
229
- ref={ref}
230
218
  renderNavPrevButton={renderPrevButton}
219
+ renderNavNextButton={renderNextButton}
231
220
  isOutsideRange={isDayDisabled}
232
221
  phrases={getCopy()}
233
- id={id}
234
- displayFormat="DD / MM / YYYY"
235
- placeholder="DD / MM / YYYY"
236
- renderNavNextButton={renderNextButton}
237
222
  renderMonthElement={({ month }) => (
238
223
  <MonthCenterContainer>
239
224
  <div>
@@ -248,8 +233,53 @@ const DatePicker = forwardRef(
248
233
  <div>{dictionary[copy] ? dictionary[copy].weekDays[day] : day}</div>
249
234
  )}
250
235
  />
251
- )}
252
- </InputSupports>
236
+ </>
237
+ ) : (
238
+ <DateInputWrapper onMouseDown={handleMouseDown} onFocus={handleFocus}>
239
+ <TextInput
240
+ copy={copy}
241
+ feedback={feedback}
242
+ hint={hint}
243
+ placeholder="DD / MM / YYYY"
244
+ onChange={onChangeInput}
245
+ tooltip={tooltip}
246
+ hintPosition={hintPosition}
247
+ label={dictionary[copy]?.roleDescription ?? label}
248
+ value={inputText}
249
+ validation={validation}
250
+ >
251
+ <SingleDatePicker
252
+ date={inputDate}
253
+ onDateChange={onChange}
254
+ focused={isFocused}
255
+ onFocusChange={onFocusChange}
256
+ numberOfMonths={1}
257
+ hideKeyboardShortcutsPanel={true}
258
+ keepOpenOnDateSelect={true}
259
+ daySize={daySize}
260
+ ref={ref}
261
+ renderNavPrevButton={renderPrevButton}
262
+ isOutsideRange={isDayDisabled}
263
+ phrases={getCopy()}
264
+ id={id}
265
+ renderNavNextButton={renderNextButton}
266
+ renderMonthElement={({ month }) => (
267
+ <MonthCenterContainer>
268
+ <div>
269
+ {dictionary[copy]
270
+ ? dictionary[copy].months[month.month()]
271
+ : month.format('MMMM')}{' '}
272
+ {month.year()}
273
+ </div>
274
+ </MonthCenterContainer>
275
+ )}
276
+ renderWeekHeaderElement={(day) => (
277
+ <div>{dictionary[copy] ? dictionary[copy].weekDays[day] : day}</div>
278
+ )}
279
+ />
280
+ </TextInput>
281
+ </DateInputWrapper>
282
+ )}
253
283
  </CalendarContainer>
254
284
  )
255
285
  }
@@ -31,13 +31,8 @@ const defaultReactDatesCss = css`
31
31
  .SingleDatePickerInput {
32
32
  display: inline-block;
33
33
  background-color: #fff;
34
- }
35
- .SingleDatePickerInput__withBorder {
36
- border-radius: 2px;
37
- border: 1px solid #dbdbdb;
38
- }
39
- .SingleDatePickerInput__rtl {
40
- direction: rtl;
34
+ position: absolute;
35
+ top: -55px;
41
36
  }
42
37
  .SingleDatePickerInput__disabled {
43
38
  background-color: #f2f2f2;
@@ -658,67 +653,8 @@ const defaultReactDatesCss = css`
658
653
  left: 0;
659
654
  overflow-y: scroll;
660
655
  }
661
- .DateInput {
662
- margin: 0;
663
- padding: 0;
664
- background: #fff;
665
- position: relative;
666
- display: inline-block;
667
- width: 130px;
668
- vertical-align: middle;
669
- }
670
- .DateInput__small {
671
- width: 97px;
672
- }
673
- .DateInput__block {
674
- width: 100%;
675
- }
676
- .DateInput__disabled {
677
- background: #f2f2f2;
678
- color: #dbdbdb;
679
- }
680
656
  .DateInput_input {
681
- font-weight: 200;
682
- font-size: 19px;
683
- line-height: 24px;
684
- color: #484848;
685
- background-color: #fff;
686
- width: 100%;
687
- padding: 11px 11px 9px;
688
- border: 0;
689
- border-top: 0;
690
- border-right: 0;
691
- border-bottom: 2px solid transparent;
692
- border-left: 0;
693
- border-radius: 0;
694
- }
695
- .DateInput_input__small {
696
- font-size: 15px;
697
- line-height: 18px;
698
- letter-spacing: 0.2px;
699
- padding: 7px 7px 5px;
700
- }
701
- .DateInput_input__regular {
702
- font-weight: auto;
703
- }
704
- .DateInput_input__readOnly {
705
- -webkit-user-select: none;
706
- -moz-user-select: none;
707
- -ms-user-select: none;
708
- user-select: none;
709
- }
710
- .DateInput_input__focused {
711
- outline: 0;
712
- background: #fff;
713
- border: 0;
714
- border-top: 0;
715
- border-right: 0;
716
- border-bottom: 2px solid #008489;
717
- border-left: 0;
718
- }
719
- .DateInput_input__disabled {
720
- background: #f2f2f2;
721
- font-style: italic;
657
+ display: none;
722
658
  }
723
659
  .DateInput_screenReaderMessage {
724
660
  border: 0;
@@ -732,6 +668,7 @@ const defaultReactDatesCss = css`
732
668
  }
733
669
  .DateInput_fang {
734
670
  position: absolute;
671
+ top: 55px;
735
672
  width: 20px;
736
673
  height: 10px;
737
674
  left: 22px;
@@ -115,21 +115,17 @@ const StoryCard = forwardRef(
115
115
  space={1}
116
116
  tokens={{ justifyContent: 'space-between', alignItems: 'baseline' }}
117
117
  >
118
- {Boolean(tag) && (
119
- <Typography variant={{ size: 'eyebrow', colour: 'secondary' }}>
120
- {tag}
121
- </Typography>
122
- )}
118
+ {Boolean(tag) && <Typography variant={{ size: 'eyebrow' }}>{tag}</Typography>}
123
119
  {Boolean(date) && (
124
120
  // TODO: get user locale and apply date formatting: "MMM DD, YYYY" for `en` and "YYYY-MM-DD" for `fr`
125
121
  // Get locale based on decision of https://github.com/telus/universal-design-system/issues/715
126
- <Typography variant={{ size: 'small', colour: 'secondary' }}>{date}</Typography>
122
+ <Typography variant={{ size: 'small' }}>{date}</Typography>
127
123
  )}
128
124
  </StackWrap>
129
125
  <Spacer space={2} />
130
126
  <Divider variant={{ decorative: true }} />
131
127
  <Spacer space={3} />
132
- <Typography variant={{ size: 'h3', colour: 'secondary' }}>{title}</Typography>
128
+ <Typography variant={{ size: 'h3' }}>{title}</Typography>
133
129
  <Spacer space={2} />
134
130
  <Typography>{description}</Typography>
135
131
  </Box>
@@ -119,7 +119,7 @@ export const VideoProps = {
119
119
  /**
120
120
  * The splash screen UI's language as an ISO language code. It currently supports English and French.
121
121
  */
122
- copy: PropTypes.oneOf(['en', 'fr']).isRequired,
122
+ copy: PropTypes.oneOf(['en', 'fr']),
123
123
  /**
124
124
  * A function to be run when the play button is pressed on the video splash screen and the video is ready to play.
125
125
  */
@@ -8,8 +8,8 @@ export interface WebVideoProps extends HTMLAttrs {
8
8
  defaultVolume?: number
9
9
  beginMuted?: boolean
10
10
  videoLength: number
11
- copy: 'en' | 'fr'
12
- onStart: () => void
11
+ copy?: 'en' | 'fr'
12
+ onStart?: () => void
13
13
  }
14
14
 
15
15
  declare const WebVideo: ComponentType<WebVideoProps>