playbook_ui 11.1.1 → 11.2.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/data/menu.yml +14 -0
  4. data/app/pb_kits/playbook/index.js +1 -0
  5. data/app/pb_kits/playbook/pb_bread_crumbs/docs/_description.md +1 -1
  6. data/app/pb_kits/playbook/pb_button_toolbar/{_button_toolbar.jsx → _button_toolbar.tsx} +3 -3
  7. data/app/pb_kits/playbook/pb_caption/_caption.tsx +1 -1
  8. data/app/pb_kits/playbook/pb_contact/_contact.jsx +7 -6
  9. data/app/pb_kits/playbook/pb_contact/contact.rb +4 -0
  10. data/app/pb_kits/playbook/pb_contact/contact.test.js +87 -0
  11. data/app/pb_kits/playbook/pb_contact/docs/_contact_with_detail.html.erb +6 -0
  12. data/app/pb_kits/playbook/pb_contact/docs/_contact_with_detail.jsx +6 -0
  13. data/app/pb_kits/playbook/pb_dialog/_dialog.jsx +61 -12
  14. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_default.jsx +1 -1
  15. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.jsx +153 -0
  16. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.md +1 -0
  17. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.jsx +130 -0
  18. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.md +1 -0
  19. data/app/pb_kits/playbook/pb_dialog/docs/example.yml +2 -0
  20. data/app/pb_kits/playbook/pb_dialog/docs/index.js +2 -0
  21. data/app/pb_kits/playbook/pb_flex/_flex_item.tsx +50 -0
  22. data/app/pb_kits/playbook/pb_icon/_icon.tsx +15 -13
  23. data/app/pb_kits/playbook/pb_lightbox/Carousel/Slide.tsx +53 -0
  24. data/app/pb_kits/playbook/pb_lightbox/Carousel/Slides.tsx +35 -0
  25. data/app/pb_kits/playbook/pb_lightbox/Carousel/Thumbnail.tsx +39 -0
  26. data/app/pb_kits/playbook/pb_lightbox/Carousel/Thumbnails.tsx +75 -0
  27. data/app/pb_kits/playbook/pb_lightbox/Carousel/index.tsx +57 -0
  28. data/app/pb_kits/playbook/pb_lightbox/_lightbox.tsx +115 -0
  29. data/app/pb_kits/playbook/pb_lightbox/_lightbox_context.tsx +3 -0
  30. data/app/pb_kits/playbook/pb_lightbox/_lightbox_header.tsx +109 -0
  31. data/app/pb_kits/playbook/pb_lightbox/_lightbox_header_icon.tsx +27 -0
  32. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_compound_component.jsx +66 -0
  33. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_compound_component.md +1 -0
  34. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_default.jsx +65 -0
  35. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_default.md +1 -0
  36. data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_multiple.jsx +91 -0
  37. data/app/pb_kits/playbook/pb_lightbox/docs/example.yml +6 -0
  38. data/app/pb_kits/playbook/pb_lightbox/docs/index.js +3 -0
  39. data/app/pb_kits/playbook/pb_lightbox/hooks/useKbdControls.ts +34 -0
  40. data/app/pb_kits/playbook/pb_lightbox/hooks/useVisibility.js +21 -0
  41. data/app/pb_kits/playbook/pb_lightbox/hooks/useWindowSize.ts +30 -0
  42. data/app/pb_kits/playbook/pb_lightbox/lightbox.scss +222 -0
  43. data/app/pb_kits/playbook/pb_lightbox/lightbox.test.jsx +124 -0
  44. data/app/pb_kits/playbook/pb_radio/_radio.tsx +86 -0
  45. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  46. data/app/pb_kits/playbook/utilities/globalProps.ts +1 -1
  47. data/dist/reset.css +60 -1
  48. data/lib/playbook/version.rb +2 -2
  49. metadata +31 -4
  50. data/app/pb_kits/playbook/pb_radio/_radio.jsx +0 -78
@@ -0,0 +1,109 @@
1
+ /* eslint-disable react/no-multi-comp */
2
+ /* @flow */
3
+ import React, { useContext } from 'react'
4
+ import classnames from 'classnames'
5
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
6
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
7
+ import { LightboxContext } from './_lightbox_context'
8
+ import { LightboxHeaderIcon } from './_lightbox_header_icon'
9
+ import { IconSizes } from '../pb_icon/_icon'
10
+
11
+ import Caption from '../pb_caption/_caption'
12
+ import Flex from '../pb_flex/_flex'
13
+ import FlexItem from '../pb_flex/_flex_item'
14
+ import Title from '../pb_title/_title'
15
+
16
+ type LightboxHeaderProps = {
17
+ aria?: {[key: string]: string},
18
+ children?: React.ReactNode[] | React.ReactNode | string,
19
+ className?: string,
20
+ closeable?: boolean,
21
+ data?: {[key: string]: string | number},
22
+ icon?: string,
23
+ iconSize?: IconSizes,
24
+ id?: string,
25
+ text?: string,
26
+ textRight?: string,
27
+ title?: string,
28
+ } & GlobalProps
29
+
30
+ const LightboxHeader = (props: LightboxHeaderProps): React.ReactElement => {
31
+ const {
32
+ aria = {},
33
+ children,
34
+ className,
35
+ data = {},
36
+ spacing = 'between',
37
+ text,
38
+ textRight = 'All Photos',
39
+ title,
40
+ closeable = true,
41
+ icon = 'times',
42
+ iconSize = '2x',
43
+ } = props
44
+
45
+ const ariaProps = buildAriaProps(aria)
46
+ const dataProps = buildDataProps(data)
47
+ const api: any = useContext(LightboxContext)
48
+ const headerCSS = buildCss('lightbox_header')
49
+ const headerSpacing = globalProps(props, { paddingY: 'sm' })
50
+
51
+ const handleOnLightboxClose = () => api.onClose()
52
+
53
+ const HeaderBody = () => (
54
+ <React.Fragment>
55
+ <FlexItem flex="1">
56
+ <LightboxHeaderIcon
57
+ icon={icon}
58
+ iconSize={iconSize}
59
+ onClose={handleOnLightboxClose}
60
+ />
61
+ </FlexItem>
62
+ {(title && text) && (
63
+ <FlexItem flex="5">
64
+ <Flex justify="center">
65
+ <Flex
66
+ align="center"
67
+ orientation="column"
68
+ >
69
+ <Title
70
+ dark
71
+ paddingBottom="xs"
72
+ size={4}
73
+ text={title}
74
+ />
75
+ <Caption dark>{text}</Caption>
76
+ </Flex>
77
+ </Flex>
78
+ </FlexItem>
79
+ ) }
80
+ <FlexItem flex="1">
81
+ <Flex justify="end">
82
+ <Title
83
+ dark
84
+ marginRight="md"
85
+ marginTop="xs"
86
+ size={4}
87
+ text={textRight}
88
+ />
89
+ </Flex>
90
+ </FlexItem>
91
+ </React.Fragment>
92
+ )
93
+
94
+ return (
95
+ <div className="carousel-header">
96
+ <Flex
97
+ {...ariaProps}
98
+ {...dataProps}
99
+ className={classnames(headerCSS, headerSpacing, className)}
100
+ spacing={spacing}
101
+ >
102
+ {closeable && <HeaderBody/>}
103
+ {children}
104
+ </Flex>
105
+ </div>
106
+ )
107
+ }
108
+
109
+ export default LightboxHeader
@@ -0,0 +1,27 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import Icon from '../pb_icon/_icon'
5
+ import {IconSizes} from '../pb_icon/_icon'
6
+
7
+ type LightboxHeaderIconProps = {
8
+ onClose: () => void,
9
+ icon: string,
10
+ iconSize: IconSizes,
11
+ }
12
+
13
+ export const LightboxHeaderIcon = (props: LightboxHeaderIconProps): React.ReactElement => {
14
+ const { onClose, icon, iconSize } = props
15
+ return (
16
+ <div
17
+ className="close-icon ml_sm"
18
+ onClick={onClose}
19
+ >
20
+ <Icon
21
+ fixedWidth
22
+ icon={icon}
23
+ size={iconSize}
24
+ />
25
+ </div>
26
+ )
27
+ }
@@ -0,0 +1,66 @@
1
+ /* @flow */
2
+ /* eslint-disable jsx-control-statements/jsx-use-if-tag */
3
+ import React, { useState } from 'react'
4
+ import { Flex, Image } from '../../'
5
+ import Lightbox from '../_lightbox.tsx'
6
+
7
+ const LightboxCompoundComponent = (props) => {
8
+ const photos = [
9
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
10
+ 'https://images.unsplash.com/photo-1501045337096-542a73dafa4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2052&q=80',
11
+ 'https://images.unsplash.com/photo-1563693998336-93c10e5d8f91?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80,',
12
+ ]
13
+ const [selectedPhoto, setSelectedPhoto] = useState(0)
14
+ const [showLightbox, toggleShowLightbox] = useState(false)
15
+
16
+ const handleCloseLightbox = () => {
17
+ toggleShowLightbox(!showLightbox)
18
+ setSelectedPhoto(null)
19
+ }
20
+
21
+ const onPhotoClick = (photo) => {
22
+ toggleShowLightbox(!showLightbox)
23
+ setSelectedPhoto(photo)
24
+ }
25
+
26
+ return (
27
+ <>
28
+ <div>
29
+ {showLightbox ? (
30
+ <Lightbox
31
+ description='Description Content Goes Here.'
32
+ initialPhoto={selectedPhoto}
33
+ onClose={handleCloseLightbox}
34
+ photos={photos}
35
+ title='Windows, Sidings, & Gutters'
36
+ {...props}
37
+ />
38
+ ) : (
39
+ <div className="PhotoViewer">
40
+ <Flex>
41
+ {photos.map((photo, index) => {
42
+ return (
43
+ <div
44
+ key={photo[index]}
45
+ onClick={() => onPhotoClick(index)}
46
+ >
47
+ <Image
48
+ marginRight="xl"
49
+ rounded
50
+ size="lg"
51
+ url={photo}
52
+ />
53
+
54
+ <div className="overlay" />
55
+ </div>
56
+ )
57
+ })}
58
+ </Flex>
59
+ </div>
60
+ )}
61
+ </div>
62
+ </>
63
+ )
64
+ }
65
+
66
+ export default LightboxCompoundComponent
@@ -0,0 +1 @@
1
+ To get the title and description to appear pass in the `title` and `description` props.
@@ -0,0 +1,65 @@
1
+ /* @flow */
2
+ /* eslint-disable jsx-control-statements/jsx-use-if-tag */
3
+ import React, { useState } from 'react'
4
+ import { Flex, Image } from '../../'
5
+ import Lightbox from '../_lightbox.tsx'
6
+
7
+ const LightboxDefault = (props) => {
8
+ const photos = [
9
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
10
+ ]
11
+ const [selectedPhoto, setSelectedPhoto] = useState(0)
12
+ const [showLightbox, toggleShowLightbox] = useState(false)
13
+
14
+ const handleCloseLightbox = () => {
15
+ toggleShowLightbox(!showLightbox)
16
+ setSelectedPhoto(null)
17
+ }
18
+
19
+ const onPhotoClick = (photoIndex) => {
20
+ toggleShowLightbox(!showLightbox)
21
+ setSelectedPhoto(photoIndex)
22
+ }
23
+
24
+ return (
25
+ <>
26
+ <div>
27
+ {showLightbox ? (
28
+ <Lightbox
29
+ icon="times"
30
+ iconSize="2x"
31
+ initialPhoto={selectedPhoto}
32
+ onClose={handleCloseLightbox}
33
+ photos={photos}
34
+ showCount={false}
35
+ {...props}
36
+ />
37
+ ) : (
38
+ <div className="PhotoViewer">
39
+ <Flex>
40
+ {photos.map((photo, index) => {
41
+ return (
42
+ <div
43
+ key={photo[index]}
44
+ onClick={() => onPhotoClick(index)}
45
+ >
46
+ <Image
47
+ marginRight="xl"
48
+ rounded
49
+ size="lg"
50
+ url={photo}
51
+ />
52
+
53
+ <div className="overlay" />
54
+ </div>
55
+ )
56
+ })}
57
+ </Flex>
58
+ </div>
59
+ )}
60
+ </div>
61
+ </>
62
+ )
63
+ }
64
+
65
+ export default LightboxDefault
@@ -0,0 +1 @@
1
+ Lightbox contains 7 props: `photos` (an array of urls), `initialPhoto` (a number), an `onClose` callback function, a `title` and `description` string, an `icon` prop that matches to our `Icon` kit, and an `iconSize` prop that also corresponds to our icon kit.
@@ -0,0 +1,91 @@
1
+ /* @flow */
2
+ /* eslint-disable jsx-control-statements/jsx-use-if-tag */
3
+ import React, { useState } from 'react'
4
+ import { Flex, Image } from '../../'
5
+ import Lightbox from '../_lightbox.tsx'
6
+
7
+ const LightboxMultiple = (props) => {
8
+ const photos = [
9
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
10
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
11
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
12
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
13
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
14
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
15
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
16
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
17
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
18
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
19
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
20
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
21
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
22
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
23
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
24
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
25
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
26
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
27
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
28
+ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80',
29
+ 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80',
30
+ 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80',
31
+ ]
32
+ const [selectedPhoto, setSelectedPhoto] = useState(0)
33
+ const [light, toggleLight] = useState(false)
34
+
35
+ const handleCloseLightbox = () => {
36
+ toggleLight(!light)
37
+ setSelectedPhoto(null)
38
+ }
39
+
40
+ const onPhotoClick = (photo) => {
41
+ toggleLight(!light)
42
+ setSelectedPhoto(photo)
43
+ }
44
+
45
+ const exampleStyles = {
46
+ width: "100%",
47
+ overflow: "auto"
48
+ }
49
+
50
+ return (
51
+ <div>
52
+ {light ? (
53
+ <Lightbox
54
+ icon="times"
55
+ iconSize="2x"
56
+ initialPhoto={selectedPhoto}
57
+ onClose={handleCloseLightbox}
58
+ photos={photos}
59
+ {...props}
60
+ />
61
+ ) : (
62
+ <div
63
+ className="PhotoViewer"
64
+ style={exampleStyles}
65
+ >
66
+ <Flex>
67
+ {photos.map((photo, index) => {
68
+ return (
69
+ <div
70
+ key={photos[index]}
71
+ onClick={() => onPhotoClick(index)}
72
+ >
73
+ <Image
74
+ marginRight="xl"
75
+ rounded
76
+ size="lg"
77
+ url={photo}
78
+ />
79
+
80
+ <div className="overlay" />
81
+ </div>
82
+ )
83
+ })}
84
+ </Flex>
85
+ </div>
86
+ )}
87
+ </div>
88
+ )
89
+ }
90
+
91
+ export default LightboxMultiple
@@ -0,0 +1,6 @@
1
+ examples:
2
+
3
+ react:
4
+ - lightbox_default: Default
5
+ - lightbox_multiple: Multiple
6
+ - lightbox_compound_component: Compound Component
@@ -0,0 +1,3 @@
1
+ export { default as LightboxDefault } from './_lightbox_default.jsx'
2
+ export { default as LightboxMultiple } from './_lightbox_multiple.jsx'
3
+ export { default as LightboxCompoundComponent } from './_lightbox_compound_component.jsx'
@@ -0,0 +1,34 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ export const useKbdControls = (api: {[key: string]: () => void}): string => {
4
+ const [cmdKey, setCmdKey] = useState('')
5
+
6
+ useEffect(() => {
7
+ const handleKeyDown = ({key}: {key: string}) => {
8
+ const keyCmd = key.toLowerCase()
9
+ setCmdKey(keyCmd)
10
+
11
+ switch(keyCmd) {
12
+ case 'escape': {
13
+ api.onClose()
14
+ break
15
+ }
16
+ case 'arrowleft': {
17
+ api.onArrowLeft()
18
+ break
19
+ }
20
+ case 'arrowright': {
21
+ api.onArrowRight()
22
+ break
23
+ }
24
+ }
25
+ }
26
+
27
+ window.addEventListener('keydown', handleKeyDown);
28
+
29
+ return () => {
30
+ window.removeEventListener('keydown', handleKeyDown);
31
+ }
32
+ }, [api])
33
+ return cmdKey
34
+ }
@@ -0,0 +1,21 @@
1
+ import { debounce } from 'lodash'
2
+ import { useCallback, useMemo, useState } from 'react'
3
+
4
+ export default function useVisibility(initialState = false) {
5
+ const [visible, setVisible] = useState(initialState)
6
+ const hide = useCallback(() => setVisible(false), [])
7
+ const show = useCallback(({ afterDelay = 0 } = {}) => {
8
+ debounce(() => setVisible(true), afterDelay)()
9
+ }, [])
10
+ const toggle = useCallback(() => setVisible((current) => !current), [])
11
+
12
+ return useMemo(
13
+ () => ({
14
+ hide,
15
+ show,
16
+ toggle,
17
+ visible,
18
+ }),
19
+ [hide, show, toggle, visible]
20
+ )
21
+ }
@@ -0,0 +1,30 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ type WindowSize = {
4
+ width: number,
5
+ height: number,
6
+ }
7
+
8
+ export const useWindowSize = (): WindowSize => {
9
+ const [size, setSize] = useState({
10
+ width: window.innerWidth,
11
+ height: window.innerHeight,
12
+ })
13
+
14
+ useEffect(() => {
15
+ const handleResize = () => {
16
+ setSize({
17
+ width: window.innerWidth,
18
+ height: window.innerHeight,
19
+ })
20
+ }
21
+
22
+ window.addEventListener('resize', handleResize)
23
+
24
+ handleResize()
25
+
26
+ return () => window.removeEventListener('resize', handleResize)
27
+ }, [])
28
+
29
+ return size
30
+ }
@@ -0,0 +1,222 @@
1
+ @import "../tokens/spacing";
2
+ @import "../tokens/screen_sizes";
3
+
4
+ $slides-margin: $space-md;
5
+
6
+ .carousel {
7
+ .home-tour-main-content {
8
+ overflow-y: hidden;
9
+ }
10
+
11
+ .image-gallery-slide-wrapper {
12
+ width: 1024px;
13
+ height: 686px;
14
+ }
15
+
16
+ .image-gallery-slide div {
17
+ height: auto;
18
+ }
19
+
20
+ .image-gallery-slide .image-gallery-image {
21
+ max-height: 100% !important;
22
+ max-width: 100% !important;
23
+ height: 692px !important;
24
+ width: 100% !important;
25
+ object-fit: cover;
26
+ }
27
+
28
+ .image-gallery-left-nav .image-gallery-svg, .image-gallery-right-nav .image-gallery-svg {
29
+ height: 120px;
30
+ width: 30px;
31
+ opacity: 0.4;
32
+ }
33
+ .image-gallery-thumbnails {
34
+ overflow-x: auto;
35
+ }
36
+
37
+ .image-gallery-thumbnails-container {
38
+ width: 1024px;
39
+ padding-left: 4px;
40
+ }
41
+
42
+ .image-gallery-thumbnails {
43
+ padding-top: 3px;
44
+ background: #000;
45
+ }
46
+
47
+ .image-gallery-thumbnail-image {
48
+ height: 64px;
49
+ width: 93px;
50
+ }
51
+
52
+ .image-gallery-thumbnail + .image-gallery-thumbnail {
53
+ margin-left: 2px;
54
+ margin-top: 2px;
55
+ }
56
+
57
+ .carousel-header {
58
+ background: rgb(0, 0, 0);
59
+ border-radius: 0px;
60
+ min-height: 51px;
61
+ position: fixed;
62
+ top: 0;
63
+ left: 0;
64
+ right: 0;
65
+ z-index: 9999999;
66
+ align-items: center;
67
+ transition: all .5s;
68
+
69
+ .close-icon {
70
+ color: white;
71
+ }
72
+ }
73
+ }
74
+
75
+ .photo-cards {
76
+ .overlay {
77
+ width: 100% !important;
78
+ height: 50% !important;
79
+ bottom: 0;
80
+ position: absolute !important;
81
+ border-radius: 0px 0px 5px 5px;
82
+ background: linear-gradient(-180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.77) 100%);
83
+ }
84
+
85
+ .overlay,
86
+ .overlay ~ .key-photo-icon,
87
+ .overlay ~ .tag-counter {
88
+ pointer-events: none;
89
+ }
90
+ }
91
+
92
+
93
+ .Lightbox {
94
+ width: 100vw;
95
+ height: 100vh;
96
+ position: fixed;
97
+ left: 0;
98
+ top: 0;
99
+ display: flex;
100
+ align-items: center;
101
+ flex-direction: column;
102
+ background-color: black;
103
+ z-index: 1;
104
+ overflow: hidden;
105
+ }
106
+
107
+ .Slides {
108
+ display: flex;
109
+ height: calc(100% - 120px);
110
+ width: 100%;
111
+ z-index: 1;
112
+
113
+ [class^="react-transform-wrapper"] {
114
+ flex-shrink: 0;
115
+ width: 100%;
116
+ height: 100%;
117
+ }
118
+
119
+ [class^="react-transform-content"] {
120
+ width: 100%;
121
+ height: 100%;
122
+ }
123
+
124
+ [class^="react-transform-component"] {
125
+ width: 100%;
126
+ height: 100%;
127
+ img {
128
+ height: 100%;
129
+ }
130
+ }
131
+
132
+ }
133
+
134
+ .Slide,
135
+ .Thumbnail {
136
+ flex-shrink: 0;
137
+ border: none;
138
+ margin: 0;
139
+ padding: 0;
140
+ cursor: pointer;
141
+ background-color: transparent;
142
+ }
143
+
144
+ .Slide {
145
+ display: flex;
146
+ justify-content: center;
147
+ align-items: center;
148
+ width: 100%;
149
+ height: 100%;
150
+ overflow: hidden;
151
+
152
+ @media only screen and (max-width: $screen-xs-max) {
153
+ margin-top: 30px;
154
+ }
155
+
156
+ img {
157
+ width: 100vw;
158
+ height: 100vh;
159
+ object-fit: contain;
160
+ }
161
+ }
162
+
163
+ .BackBtn,
164
+ .NextBtn {
165
+ z-index: 2;
166
+ color: black;
167
+ position: absolute;
168
+ width: 50px;
169
+ height: 50px;
170
+ top: calc(50vh - 5px);
171
+ border: none;
172
+ border-radius: 50%;
173
+ background-color: white;
174
+ }
175
+
176
+ .BackBtn::before,
177
+ .NextBtn::before {
178
+ content: "▸";
179
+ }
180
+
181
+ .BackBtn {
182
+ left: 30px;
183
+ transform: rotate(180deg);
184
+ }
185
+
186
+ .NextBtn {
187
+ right: 30px;
188
+ }
189
+
190
+ .Thumbnails {
191
+ display: flex;
192
+ padding: 3px;
193
+ overflow: auto;
194
+ position: absolute;
195
+ z-index: 1;
196
+ left: 0;
197
+ right: 0;
198
+ bottom: 0;
199
+ &.centered {
200
+ justify-content: center;
201
+ }
202
+ }
203
+
204
+ .Thumbnails.draggable {
205
+ align-self: flex-start;
206
+ }
207
+
208
+ .Thumbnail {
209
+ padding: 3px;
210
+ height: 100%;
211
+
212
+ img {
213
+ width: 100%;
214
+ height: 100%;
215
+ }
216
+ }
217
+
218
+ .Thumbnail.active {
219
+ padding: 6px;
220
+ background-color: white;
221
+ box-shadow: 0 0 6px white;
222
+ }