@telus-uds/components-web 2.26.0 → 2.28.0

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +31 -2
  2. package/lib/DatePicker/DatePicker.js +129 -69
  3. package/lib/Image/Image.js +20 -44
  4. package/lib/Image/index.js +11 -1
  5. package/lib/Image/server.js +12 -0
  6. package/lib/OptimizeImage/OptimizeImage.js +1 -1
  7. package/lib/OptimizeImage/utils/getFallbackUrl.js +2 -2
  8. package/lib/Table/Cell.js +14 -5
  9. package/lib/baseExports.js +6 -0
  10. package/lib/index.js +12 -2
  11. package/lib/server.js +13 -0
  12. package/lib/utils/theming/get-theme-from-server.js +24 -0
  13. package/lib/utils/theming/with-client-theme.js +32 -0
  14. package/lib/utils/theming/with-server-theme.js +34 -0
  15. package/lib-module/DatePicker/DatePicker.js +132 -72
  16. package/lib-module/Image/Image.js +17 -41
  17. package/lib-module/Image/index.js +6 -1
  18. package/lib-module/Image/server.js +4 -0
  19. package/lib-module/OptimizeImage/OptimizeImage.js +1 -1
  20. package/lib-module/OptimizeImage/utils/getFallbackUrl.js +2 -2
  21. package/lib-module/Table/Cell.js +14 -5
  22. package/lib-module/baseExports.js +1 -1
  23. package/lib-module/index.js +3 -1
  24. package/lib-module/server.js +5 -0
  25. package/lib-module/utils/theming/get-theme-from-server.js +16 -0
  26. package/lib-module/utils/theming/with-client-theme.js +24 -0
  27. package/lib-module/utils/theming/with-server-theme.js +26 -0
  28. package/package.json +25 -4
  29. package/src/DatePicker/DatePicker.jsx +125 -63
  30. package/src/Image/Image.jsx +15 -24
  31. package/src/Image/index.js +6 -1
  32. package/src/Image/server.js +5 -0
  33. package/src/OptimizeImage/OptimizeImage.jsx +1 -1
  34. package/src/OptimizeImage/utils/getFallbackUrl.js +2 -2
  35. package/src/Table/Cell.jsx +9 -2
  36. package/src/baseExports.js +1 -0
  37. package/src/index.js +3 -1
  38. package/src/server.js +5 -0
  39. package/src/utils/theming/get-theme-from-server.js +22 -0
  40. package/src/utils/theming/with-client-theme.jsx +20 -0
  41. package/src/utils/theming/with-server-theme.jsx +21 -0
  42. package/types/WebVideo.d.ts +4 -3
package/package.json CHANGED
@@ -5,18 +5,37 @@
5
5
  ],
6
6
  "dependencies": {
7
7
  "@gorhom/portal": "^1.0.14",
8
- "@telus-uds/components-base": "1.71.0",
8
+ "@telus-uds/components-base": "1.73.0",
9
9
  "@telus-uds/system-constants": "^1.3.0",
10
10
  "fscreen": "^1.2.0",
11
11
  "lodash.omit": "^4.5.0",
12
+ "moment": "2.29.4",
12
13
  "react-dates": "^21.8.0",
13
14
  "react-helmet-async": "^1.3.0",
14
15
  "react-moment-proptypes": "^1.8.1",
15
- "@telus-uds/system-theme-tokens": "^2.47.0",
16
+ "@telus-uds/system-theme-tokens": "^2.49.0",
16
17
  "prop-types": "^15.7.2",
17
18
  "lodash.throttle": "^4.1.1",
18
19
  "react-youtube": "^10.1.0",
19
- "moment": "2.29.4"
20
+ "semver": "^7.5.4"
21
+ },
22
+ "exports": {
23
+ ".": {
24
+ "import": "./lib-module/index.js",
25
+ "require": "./lib/index.js"
26
+ },
27
+ "./*": {
28
+ "import": "./lib-module/*/index.js",
29
+ "require": "./lib/*/index.js"
30
+ },
31
+ "./server": {
32
+ "import": "./lib-module/server.js",
33
+ "require": "./lib/server.js"
34
+ },
35
+ "./server/*": {
36
+ "import": "./lib-module/*/server.js",
37
+ "require": "./lib/server/*/server.js"
38
+ }
20
39
  },
21
40
  "description": "UDS mult-brand web components",
22
41
  "devDependencies": {
@@ -27,6 +46,8 @@
27
46
  "assert": "^2.0.0",
28
47
  "babel-plugin-react-native-web": "^0.18.7",
29
48
  "babel-plugin-styled-components": "^2.0.6",
49
+ "eslint-import-resolver-alias": "^1.1.2",
50
+ "eslint-import-resolver-exports": "^1.0.0-beta.5",
30
51
  "jest-axe": "^6.0.0",
31
52
  "jest-styled-components": "^7.0.8",
32
53
  "react-test-renderer": "~18.0.0",
@@ -62,5 +83,5 @@
62
83
  "skip": true
63
84
  },
64
85
  "types": "types/index.d.ts",
65
- "version": "2.26.0"
86
+ "version": "2.28.0"
66
87
  }
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, useEffect, useState } from 'react'
1
+ import React, { forwardRef, useEffect, useState, useRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import styled from 'styled-components'
4
4
  import momentPropTypes from 'react-moment-proptypes'
@@ -13,10 +13,12 @@ import {
13
13
  useViewport,
14
14
  useThemeTokens,
15
15
  applyTextStyles,
16
- getTokensPropType
16
+ getTokensPropType,
17
+ Portal,
18
+ useSafeLayoutEffect
17
19
  } from '@telus-uds/components-base'
18
20
  import moment from 'moment'
19
- import { isUndefined } from 'lodash'
21
+ import { isUndefined, throttle } from 'lodash'
20
22
  import CalendarContainer from './CalendarContainer'
21
23
  import dictionary from './dictionary'
22
24
  import { htmlAttrs } from '../utils'
@@ -48,6 +50,12 @@ const DateInputWrapper = styled.div({
48
50
  flexDirection: 'column'
49
51
  })
50
52
 
53
+ const PortalPositionedContainer = styled.div({
54
+ position: 'absolute',
55
+ left: ({ left }) => `${left}px`,
56
+ top: ({ top }) => `${top}px`
57
+ })
58
+
51
59
  /**
52
60
  * Use DatePicker to select a date on a calendar.
53
61
  *
@@ -97,6 +105,23 @@ const DatePicker = forwardRef(
97
105
  const [inputText, setInputText] = useState(
98
106
  date instanceof moment ? date.format(dateFormat) : ''
99
107
  )
108
+ const textInputRef = useRef()
109
+ const [datePickerPosition, setDatePickerPosition] = useState({ left: 0, top: 0 })
110
+
111
+ useSafeLayoutEffect(() => {
112
+ const updateDimensions = () => {
113
+ if (inline) return
114
+ const { left, top } = textInputRef.current.getBoundingClientRect()
115
+ setDatePickerPosition({
116
+ left,
117
+ top: top + textInputRef.current.offsetHeight
118
+ })
119
+ }
120
+ const throttledUpdateDimensions = throttle(updateDimensions, 100, { leading: false })
121
+ updateDimensions()
122
+ window.addEventListener('resize', throttledUpdateDimensions)
123
+ return () => window.removeEventListener('resize', throttledUpdateDimensions)
124
+ }, [])
100
125
 
101
126
  const [isFocused, setIsFocused] = useState(false)
102
127
  const [isClickedInside, setIsClickedInside] = useState(false)
@@ -204,19 +229,7 @@ const DatePicker = forwardRef(
204
229
  />
205
230
  )
206
231
  return (
207
- <CalendarContainer
208
- {...selectProps(rest)}
209
- daySize={daySize}
210
- validation={validation}
211
- remainingTokens={{
212
- ...remainingTokens
213
- }}
214
- calendarDayDefaultHeight={circleSize}
215
- calendarDayDefaultWidth={circleSize}
216
- calendarMonthFontTokens={calendarMonthFontTokens}
217
- calendarWeekFontTokens={calendarWeekFontTokens}
218
- defaultFontTokens={defaultFontTokens}
219
- >
232
+ <>
220
233
  {inline ? (
221
234
  <>
222
235
  <HiddenInputFieldContainer
@@ -225,65 +238,30 @@ const DatePicker = forwardRef(
225
238
  >
226
239
  <input ref={ref} id={id} type="text" value={inputText} readOnly />
227
240
  </HiddenInputFieldContainer>
228
- <DayPickerSingleDateController
229
- date={inputDate}
230
- onDateChange={onChange}
231
- focused={isFocused}
232
- onFocusChange={onFocusChange}
233
- numberOfMonths={1}
234
- hideKeyboardShortcutsPanel={true}
235
- keepOpenOnDateSelect={false}
241
+ <CalendarContainer
242
+ {...selectProps(rest)}
236
243
  daySize={daySize}
237
- renderNavPrevButton={renderPrevButton}
238
- renderNavNextButton={renderNextButton}
239
- isOutsideRange={isDayDisabled}
240
- phrases={getCopy()}
241
- renderMonthElement={({ month }) => (
242
- <MonthCenterContainer>
243
- <div>
244
- {dictionary[copy]
245
- ? dictionary[copy].months[month.month()]
246
- : month.format('MMMM')}{' '}
247
- {month.year()}
248
- </div>
249
- </MonthCenterContainer>
250
- )}
251
- renderWeekHeaderElement={(day) => (
252
- <div>{dictionary[copy] ? dictionary[copy].weekDays[day] : day}</div>
253
- )}
254
- />
255
- </>
256
- ) : (
257
- <DateInputWrapper onMouseDown={handleMouseDown} onFocus={handleFocus}>
258
- <TextInput
259
- copy={copy}
260
- feedback={feedback}
261
- hint={hint}
262
- placeholder="DD / MM / YYYY"
263
- onChange={onChangeInput}
264
- tooltip={tooltip}
265
- hintPosition={hintPosition}
266
- label={dictionary[copy]?.roleDescription ?? label}
267
- value={inputText}
268
244
  validation={validation}
269
- inactive={disabled}
245
+ remainingTokens={remainingTokens}
246
+ calendarDayDefaultHeight={circleSize}
247
+ calendarDayDefaultWidth={circleSize}
248
+ calendarMonthFontTokens={calendarMonthFontTokens}
249
+ calendarWeekFontTokens={calendarWeekFontTokens}
250
+ defaultFontTokens={defaultFontTokens}
270
251
  >
271
- <SingleDatePicker
252
+ <DayPickerSingleDateController
272
253
  date={inputDate}
273
- disabled={disabled}
274
254
  onDateChange={onChange}
275
255
  focused={isFocused}
276
256
  onFocusChange={onFocusChange}
277
257
  numberOfMonths={1}
278
258
  hideKeyboardShortcutsPanel={true}
279
- keepOpenOnDateSelect={true}
259
+ keepOpenOnDateSelect={false}
280
260
  daySize={daySize}
281
- ref={ref}
282
261
  renderNavPrevButton={renderPrevButton}
262
+ renderNavNextButton={renderNextButton}
283
263
  isOutsideRange={isDayDisabled}
284
264
  phrases={getCopy()}
285
- id={id}
286
- renderNavNextButton={renderNextButton}
287
265
  renderMonthElement={({ month }) => (
288
266
  <MonthCenterContainer>
289
267
  <div>
@@ -298,10 +276,94 @@ const DatePicker = forwardRef(
298
276
  <div>{dictionary[copy] ? dictionary[copy].weekDays[day] : day}</div>
299
277
  )}
300
278
  />
279
+ </CalendarContainer>
280
+ </>
281
+ ) : (
282
+ <DateInputWrapper onMouseDown={handleMouseDown} onFocus={handleFocus}>
283
+ <TextInput
284
+ copy={copy}
285
+ feedback={feedback}
286
+ hint={hint}
287
+ placeholder="DD / MM / YYYY"
288
+ onChange={onChangeInput}
289
+ tooltip={tooltip}
290
+ hintPosition={hintPosition}
291
+ label={dictionary[copy]?.roleDescription ?? label}
292
+ value={inputText}
293
+ validation={validation}
294
+ inactive={disabled}
295
+ ref={textInputRef}
296
+ >
297
+ <Portal>
298
+ {/* Because `SingleDatePicker` is an absolutely positioned element,
299
+ * putting it in a `Portal` breaks view heirarchy because it doesn't
300
+ * align with `TextInput`, but rather position itself with the nearest
301
+ * positioned ancestor.
302
+ *
303
+ * This means that the `Portal` needs to be positioned absolutely,
304
+ * but the `SingleDatePicker` needs to be positioned relative to the
305
+ * `Portal`.
306
+ *
307
+ * This is accomplished by wrapping the `SingleDatePicker` in a
308
+ * `PortalPositionedContainer` which positions the `SingleDatePicker`
309
+ * relative to the `Portal`. This container is then positioned absolutely
310
+ * relative to the `TextInput`.
311
+ *
312
+ * TODO: Using `floating-ui` or something like that is a more preferred and streamlined way
313
+ * to position popovers and overlays.
314
+ */}
315
+ <PortalPositionedContainer
316
+ top={datePickerPosition.top}
317
+ left={datePickerPosition.left}
318
+ >
319
+ <CalendarContainer
320
+ {...selectProps(rest)}
321
+ daySize={daySize}
322
+ validation={validation}
323
+ remainingTokens={remainingTokens}
324
+ calendarDayDefaultHeight={circleSize}
325
+ calendarDayDefaultWidth={circleSize}
326
+ calendarMonthFontTokens={calendarMonthFontTokens}
327
+ calendarWeekFontTokens={calendarWeekFontTokens}
328
+ defaultFontTokens={defaultFontTokens}
329
+ >
330
+ <SingleDatePicker
331
+ date={inputDate}
332
+ disabled={disabled}
333
+ onDateChange={onChange}
334
+ focused={isFocused}
335
+ onFocusChange={onFocusChange}
336
+ numberOfMonths={1}
337
+ hideKeyboardShortcutsPanel={true}
338
+ keepOpenOnDateSelect={true}
339
+ daySize={daySize}
340
+ ref={ref}
341
+ renderNavPrevButton={renderPrevButton}
342
+ isOutsideRange={isDayDisabled}
343
+ phrases={getCopy()}
344
+ id={id}
345
+ renderNavNextButton={renderNextButton}
346
+ renderMonthElement={({ month }) => (
347
+ <MonthCenterContainer>
348
+ <div>
349
+ {dictionary[copy]
350
+ ? dictionary[copy].months[month.month()]
351
+ : month.format('MMMM')}{' '}
352
+ {month.year()}
353
+ </div>
354
+ </MonthCenterContainer>
355
+ )}
356
+ renderWeekHeaderElement={(day) => (
357
+ <div>{dictionary[copy] ? dictionary[copy].weekDays[day] : day}</div>
358
+ )}
359
+ />
360
+ </CalendarContainer>
361
+ </PortalPositionedContainer>
362
+ </Portal>
301
363
  </TextInput>
302
364
  </DateInputWrapper>
303
365
  )}
304
- </CalendarContainer>
366
+ </>
305
367
  )
306
368
  }
307
369
  )
@@ -1,24 +1,10 @@
1
1
  import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
- import styled from 'styled-components'
4
- import { selectSystemProps, useThemeTokens, getTokensPropType } from '@telus-uds/components-base'
5
- import { htmlAttrs, warn } from '../utils'
3
+ import { htmlAttrs, selectSystemProps, getTokensPropType } from '@telus-uds/components-base/server'
4
+ import { warn } from '../utils/logger'
6
5
 
7
6
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
8
7
 
9
- const StyledImage = styled.img(({ height }) => {
10
- return {
11
- height: height ?? 'auto',
12
- maxWidth: '100%'
13
- }
14
- })
15
- const StyledRoundedImage = styled(StyledImage)`
16
- border-radius: ${({ borderRadius }) => borderRadius}px;
17
- `
18
- const StyledCircularImage = styled(StyledImage)({
19
- borderRadius: '50%'
20
- })
21
-
22
8
  const Image = ({
23
9
  src,
24
10
  width,
@@ -27,10 +13,11 @@ const Image = ({
27
13
  rounded,
28
14
  loading = 'eager',
29
15
  tokens,
16
+ theme,
30
17
  variant,
31
18
  ...rest
32
19
  }) => {
33
- const { borderRadius } = useThemeTokens('Image', tokens, variant)
20
+ let { borderRadius } = theme
34
21
  const isCircle = rounded === 'circle'
35
22
  const isCorners = rounded === 'corners'
36
23
  const isSquare = width === height
@@ -42,19 +29,21 @@ const Image = ({
42
29
  )
43
30
  }
44
31
 
45
- let ImageComponent
46
32
  if (isCircle) {
47
- ImageComponent = StyledCircularImage
33
+ borderRadius = '50%'
48
34
  } else if (isCorners) {
49
- ImageComponent = StyledRoundedImage
50
- } else {
51
- ImageComponent = StyledImage
35
+ borderRadius = '4px'
52
36
  }
53
37
 
38
+ const style = {
39
+ borderRadius,
40
+ height: height ?? 'auto',
41
+ maxWidth: '100%'
42
+ }
54
43
  return (
55
- <ImageComponent
44
+ <img
56
45
  {...selectProps(rest)}
57
- borderRadius={borderRadius}
46
+ style={style}
58
47
  src={src}
59
48
  width={width}
60
49
  height={height}
@@ -97,4 +86,6 @@ Image.propTypes = {
97
86
  tokens: getTokensPropType('Image')
98
87
  }
99
88
 
89
+ Image.displayName = 'Image'
90
+
100
91
  export default Image
@@ -1,3 +1,8 @@
1
1
  import Image from './Image'
2
+ import withClientTheme from '../utils/theming/with-client-theme'
2
3
 
3
- export default Image
4
+ // Exporting the unwrapped component separately for react-docgen to extract info for docsite
5
+ export { Image as DefaultImage }
6
+
7
+ const ClientThemedImage = withClientTheme(Image)
8
+ export default ClientThemedImage
@@ -0,0 +1,5 @@
1
+ import withServerTheme from '../utils/theming/with-server-theme'
2
+ import Image from './Image'
3
+
4
+ const ServerThemedImage = withServerTheme(Image, 'Image')
5
+ export default ServerThemedImage
@@ -69,7 +69,7 @@ const OptimizeImage = ({
69
69
  disableRetina,
70
70
  supportsWebp
71
71
  ),
72
- fallbackSrc: getFallbackUrl(contentfulAssetUrl, xl, quality)
72
+ fallbackSrc: getFallbackUrl(contentfulAssetUrl, dimension, xl, quality)
73
73
  })
74
74
  })
75
75
  }, [contentfulAssetUrl, dimension, disableRetina, lg, md, quality, sm, xl, xs])
@@ -1,8 +1,8 @@
1
1
  import isSvgUrl from './isSvgUrl'
2
2
 
3
- export default function getFallbackUrl(url, width, quality) {
3
+ export default function getFallbackUrl(url, dimension, size, quality) {
4
4
  if (!isSvgUrl(url)) {
5
- return `${url}?w=${width}&q=${quality}`
5
+ return `${url}?${dimension}=${size}&q=${quality}`
6
6
  }
7
7
 
8
8
  return url
@@ -59,6 +59,11 @@ const createStyledCell = (htmlElement) => styled[htmlElement]`
59
59
  ? `inset 0 1px 0 ${cellBoxShadowColor}, inset 0 -1px 0 ${cellBoxShadowColor}`
60
60
  : `inset 0 1px 0 ${cellBoxShadowColor}`
61
61
  }};
62
+ ${({ display }) =>
63
+ display &&
64
+ `*:not(:empty) {
65
+ display: ${display};
66
+ }`}
62
67
  `
63
68
  const StyledHeaderCell = createStyledCell('th')
64
69
  const StyledDataCell = createStyledCell('td')
@@ -81,7 +86,8 @@ const Cell = ({ children, isFirstInRow, align = 'left', tokens: cellTokens, type
81
86
  fontSize,
82
87
  lineHeight,
83
88
  stickyBackgroundColor,
84
- fontColor
89
+ fontColor,
90
+ display
85
91
  } = useThemeTokens('Table', themeTokens, { spacing, type, text })
86
92
 
87
93
  const sharedProps = {
@@ -95,7 +101,8 @@ const Cell = ({ children, isFirstInRow, align = 'left', tokens: cellTokens, type
95
101
  cellPaddingLeft,
96
102
  cellPaddingBottom,
97
103
  stickyBackgroundColor,
98
- cellBoxShadowColor
104
+ cellBoxShadowColor,
105
+ display
99
106
  }
100
107
 
101
108
  const typographyTokens = {
@@ -22,6 +22,7 @@ export {
22
22
  Checkbox,
23
23
  CheckboxGroup,
24
24
  ChevronLink,
25
+ ColourToggle,
25
26
  Divider,
26
27
  ExpandCollapse,
27
28
  Feedback,
package/src/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ 'use client'
2
+
1
3
  export { default as Badge } from './Badge'
2
4
  export { default as OrderedList } from './OrderedList'
3
5
  export { default as PreviewCard } from './PreviewCard'
@@ -13,6 +15,7 @@ export { default as PriceLockup } from './PriceLockup'
13
15
  export { default as Footnote } from './Footnote'
14
16
  export { default as QuantitySelector } from './QuantitySelector'
15
17
  export { default as IconButton } from './IconButton'
18
+ export { default as Image, DefaultImage } from './Image'
16
19
  export { transformGradient } from './utils'
17
20
  export { default as Breadcrumbs } from './Breadcrumbs'
18
21
  export { default as BlockQuote } from './BlockQuote'
@@ -20,7 +23,6 @@ export { default as OptimizeImage } from './OptimizeImage'
20
23
  export { default as Testimonial } from './Testimonial'
21
24
  export { default as Toast } from './Toast'
22
25
  export { default as Table } from './Table'
23
- export { default as Image } from './Image'
24
26
  export { default as WebVideo } from './WebVideo'
25
27
  export { default as WaffleGrid } from './WaffleGrid'
26
28
  export { default as Spinner } from './Spinner'
package/src/server.js ADDED
@@ -0,0 +1,5 @@
1
+ import ServerThemedImage from './Image/server'
2
+
3
+ // Export themed components
4
+ /* eslint-disable import/prefer-default-export */
5
+ export { ServerThemedImage as Image }
@@ -0,0 +1,22 @@
1
+ const cachedTheme = {}
2
+ const theme = process.env.UDS_THEME
3
+
4
+ async function importTheme(componentName) {
5
+ try {
6
+ cachedTheme[componentName] = await import(
7
+ `@telus-uds/theme-${theme}/build/rn/${componentName}.js`
8
+ )
9
+ } catch (_) {
10
+ throw new Error(
11
+ `An error occurred while trying to import theme-${process.env.UDS_THEME}. Please check that the theme has been installed in your app or that you are not importing a server component inside a client component.`
12
+ )
13
+ }
14
+ }
15
+
16
+ export default async function getTheme(componentName) {
17
+ if (cachedTheme[componentName]) {
18
+ return cachedTheme[componentName]
19
+ }
20
+ await importTheme(componentName)
21
+ return cachedTheme[componentName]
22
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+
4
+ import { useThemeTokens } from '@telus-uds/components-base'
5
+
6
+ const withClientTheme = (Component) => {
7
+ const UdsStyledComponent = ({ tokens: tokenOverrides, variant, ...props }) => {
8
+ const theme = useThemeTokens(Component.displayName, variant, tokenOverrides)
9
+ return <Component theme={theme} {...props} />
10
+ }
11
+
12
+ UdsStyledComponent.propTypes = {
13
+ tokens: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
14
+ variant: PropTypes.string
15
+ }
16
+
17
+ return UdsStyledComponent
18
+ }
19
+
20
+ export default withClientTheme
@@ -0,0 +1,21 @@
1
+ import React from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { getThemeTokens } from '@telus-uds/components-base/server'
4
+
5
+ import getTheme from './get-theme-from-server'
6
+
7
+ const withServerTheme = (Component, componentName) => {
8
+ const UdsStyledComponent = async ({ tokens: tokenOverrides, variant, ...props }) => {
9
+ const componentTheme = await getTheme(componentName)
10
+ const themeTokens = getThemeTokens(componentTheme, tokenOverrides, variant)
11
+ return <Component theme={themeTokens} {...props} />
12
+ }
13
+ UdsStyledComponent.propTypes = {
14
+ tokens: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
15
+ variant: PropTypes.string
16
+ }
17
+
18
+ return UdsStyledComponent
19
+ }
20
+
21
+ export default withServerTheme
@@ -1,4 +1,5 @@
1
1
  import type { ComponentType } from 'react'
2
+ import { YouTubeEvent } from 'react-youtube'
2
3
  import type { HTMLAttrs } from './common'
3
4
 
4
5
  export interface WebVideoProps extends HTMLAttrs {
@@ -10,9 +11,9 @@ export interface WebVideoProps extends HTMLAttrs {
10
11
  videoLength: number
11
12
  copy?: 'en' | 'fr'
12
13
  onStart?: () => void
13
- onPlay?: () => void
14
- onEnd?: () => void
15
- onPause?: () => void
14
+ onPlay?: (event: YouTubeEvent<number>) => void
15
+ onEnd?: (event: YouTubeEvent<number>) => void
16
+ onPause?: (event: YouTubeEvent<number>) => void
16
17
  }
17
18
 
18
19
  declare const WebVideo: ComponentType<WebVideoProps>