playbook_ui 11.1.1 → 11.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }