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,130 @@
1
+ /* eslint-disable react/jsx-handler-names */
2
+ /* @flow */
3
+
4
+ import React, { useState } from "react"
5
+ import { Button, Dialog, Flex } from "../.."
6
+
7
+ const useDialog = (visible = false) => {
8
+ const [opened, setOpened] = useState(visible)
9
+ const toggle = () => setOpened(!opened)
10
+ return [opened, toggle]
11
+
12
+ }
13
+
14
+ const DialogStatus = () => {
15
+ const [infoAlertOpened, toggleInfoAlert] = useDialog()
16
+ const [cautionAlertOpened, toggleCautionAlert] = useDialog()
17
+ const [successAlertOpened, toggleSuccessAlert] = useDialog()
18
+ const [errorAlertOpened, toggleErrorAlert] = useDialog()
19
+ const [deleteAlertOpened, toggleDeleteAlert] = useDialog()
20
+
21
+ const dialogs = [
22
+ {
23
+ status: "info",
24
+ text: "Text explaining why there is an alert",
25
+ title: "Are you Sure?",
26
+ toggle: toggleInfoAlert,
27
+ visible: infoAlertOpened,
28
+ buttonOneText:"No, Cancel",
29
+ buttonTwoText: "Yes, Action"
30
+ },
31
+ {
32
+ status: "caution",
33
+ text: "This is the action you will be taking",
34
+ title: "Are you Sure?",
35
+ toggle: toggleCautionAlert,
36
+ visible: cautionAlertOpened,
37
+ buttonOneText:"No, Cancel",
38
+ buttonTwoText: "Yes, Action"
39
+ },
40
+ {
41
+ status: "delete",
42
+ text: "You are about to delete ...",
43
+ title: "Delete",
44
+ toggle: toggleDeleteAlert,
45
+ visible: deleteAlertOpened,
46
+ buttonOneText:"No, Cancel",
47
+ buttonTwoText: "Yes, Delete"
48
+ },
49
+ {
50
+ status: "error",
51
+ text: "Text explaining the error",
52
+ title: "Error Message",
53
+ toggle: toggleErrorAlert,
54
+ visible: errorAlertOpened,
55
+ buttonOneText:"No, Cancel",
56
+ buttonTwoText: "Ok, Thanks"
57
+ },
58
+ {
59
+ status: "success",
60
+ text: "Text explaining what is successful",
61
+ title: "Success!",
62
+ toggle: toggleSuccessAlert,
63
+ visible: successAlertOpened,
64
+ buttonOneText:"No, Cancel",
65
+ buttonTwoText: "Ok, Thanks"
66
+ },
67
+ ]
68
+
69
+ return (
70
+ <div>
71
+ <Flex>
72
+ <Button
73
+ marginRight="md"
74
+ onClick={toggleInfoAlert}
75
+ >
76
+ {"Information Status"}
77
+ </Button>
78
+ <Button
79
+ marginRight="md"
80
+ onClick={toggleCautionAlert}
81
+ >
82
+ {"Caution Status"}
83
+ </Button>
84
+ <Button
85
+ marginRight="md"
86
+ onClick={toggleSuccessAlert}
87
+ >
88
+ {"Success Status"}
89
+ </Button>
90
+ <Button onClick={toggleErrorAlert}>
91
+ {"Error Status"}
92
+ </Button>
93
+ <Button
94
+ marginRight="md"
95
+ onClick={toggleDeleteAlert}
96
+ >
97
+ {"Delete Status"}
98
+ </Button>
99
+ </Flex>
100
+ <Flex>
101
+ {dialogs.map((dialog) => (
102
+ <Dialog
103
+ key={dialog.status}
104
+ onClose={dialog.toggle}
105
+ opened={dialog.visible}
106
+ status={dialog.status}
107
+ text={dialog.text}
108
+ title={dialog.title}
109
+ >
110
+ <Dialog.Footer>
111
+ <Button
112
+ onClick={dialog.toggle}
113
+ variant="secondary"
114
+ >
115
+ {dialog.buttonOneText}
116
+ </Button>
117
+ <Button
118
+ onClick={dialog.toggle}
119
+ >
120
+ {dialog.buttonTwoText}
121
+ </Button>
122
+ </Dialog.Footer>
123
+ </Dialog>
124
+ ))}
125
+ </Flex>
126
+ </div>
127
+ )
128
+ }
129
+
130
+ export default DialogStatus
@@ -0,0 +1 @@
1
+ This shows the different alert statuses that can be used for dialog boxes. These all have two buttons which is a default
@@ -8,3 +8,5 @@ examples:
8
8
  - dialog_sizes: Sizes
9
9
  - dialog_scrollable: Scrollable
10
10
  - dialog_should_close_on_overlay: Overlay Click
11
+ - dialog_status: Status Alert
12
+ - dialog_stacked_alert: Stacked Button Alert
@@ -4,3 +4,5 @@ export { default as DialogSizes } from './_dialog_sizes.jsx'
4
4
  export { default as DialogScrollable } from './_dialog_scrollable.jsx'
5
5
  export { default as DialogSeparators } from './_dialog_separators.jsx'
6
6
  export { default as DialogShouldCloseOnOverlay } from './_dialog_should_close_on_overlay.jsx'
7
+ export { default as DialogStatus } from './_dialog_status.jsx'
8
+ export { default as DialogStackedAlert } from './_dialog_stacked_alert.jsx'
@@ -0,0 +1,50 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+ import { buildCss } from '../utilities/props'
4
+ import { globalProps, GlobalProps } from '../utilities/globalProps'
5
+ type FlexItemPropTypes = {
6
+ children: React.ReactNode[] | React.ReactNode,
7
+ fixedSize?: string,
8
+ grow?: boolean,
9
+ shrink?: boolean,
10
+ className?: string,
11
+ overflow?: "auto" | "hidden" | "initial" | "inherit" | "scroll" | "visible",
12
+ order?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'first' | 'none',
13
+ alignSelf?: "start" | "end" | "center" | "stretch" | null,
14
+ displayFlex?: boolean
15
+ } & GlobalProps
16
+
17
+ const FlexItem = (props: FlexItemPropTypes): React.ReactElement => {
18
+ const {
19
+ children,
20
+ className,
21
+ fixedSize,
22
+ grow,
23
+ overflow = null,
24
+ shrink,
25
+ flex = 'none',
26
+ order = 'none',
27
+ alignSelf,
28
+ displayFlex
29
+ } = props
30
+ const growClass = grow === true ? 'grow' : ''
31
+ const displayFlexClass = displayFlex === true ? `display_flex_${displayFlex}` : ''
32
+ const flexClass = flex !== 'none' ? `flex_${flex}` : ''
33
+ const overflowClass = overflow ? `overflow_${overflow}` : ''
34
+ const shrinkClass = shrink === true ? 'shrink' : ''
35
+ const alignSelfClass = alignSelf ? `align_self_${alignSelf}` : ''
36
+ const fixedStyle =
37
+ fixedSize !== undefined ? { flexBasis: `${fixedSize}` } : null
38
+ const orderClass = order !== 'none' ? `order_${order}` : null
39
+
40
+ return (
41
+ <div
42
+ className={classnames(buildCss('pb_flex_item_kit', growClass, shrinkClass, flexClass, displayFlexClass), overflowClass, orderClass, alignSelfClass, globalProps(props), className)}
43
+ style={fixedStyle}
44
+ >
45
+ {children}
46
+ </div>
47
+ )
48
+ }
49
+
50
+ export default FlexItem
@@ -3,6 +3,20 @@ import classnames from 'classnames'
3
3
  import { buildAriaProps, buildDataProps } from '../utilities/props'
4
4
  import { GlobalProps, globalProps } from '../utilities/globalProps'
5
5
 
6
+ export type IconSizes = "lg"
7
+ | "xs"
8
+ | "sm"
9
+ | "1x"
10
+ | "2x"
11
+ | "3x"
12
+ | "4x"
13
+ | "5x"
14
+ | "6x"
15
+ | "7x"
16
+ | "8x"
17
+ | "9x"
18
+ | "10x"
19
+
6
20
  type IconProps = {
7
21
  aria?: {[key: string]: string},
8
22
  border?: string,
@@ -18,19 +32,7 @@ type IconProps = {
18
32
  pull?: "left" | "right" | "none",
19
33
  pulse?: boolean,
20
34
  rotation?: 90 | 180 | 270,
21
- size?: | "lg"
22
- | "xs"
23
- | "sm"
24
- | "1x"
25
- | "2x"
26
- | "3x"
27
- | "4x"
28
- | "5x"
29
- | "6x"
30
- | "7x"
31
- | "8x"
32
- | "9x"
33
- | "10x",
35
+ size?: IconSizes,
34
36
  spin?: boolean,
35
37
  } & GlobalProps
36
38
 
@@ -0,0 +1,53 @@
1
+ /* @flow */
2
+
3
+ import React from 'react'
4
+ import { noop } from 'lodash'
5
+ import { TransformComponent, TransformWrapper } from 'react-zoom-pan-pinch'
6
+ import Image from '../../pb_image/_image'
7
+
8
+ type SlideType = {
9
+ alt?: string,
10
+ current?: number,
11
+ onClick: () => void,
12
+ onChange?: (index: number) => void,
13
+ onZoom: (zoom: boolean) => void,
14
+ zooming: boolean,
15
+ url: string,
16
+ }
17
+
18
+ export default function Slide({
19
+ alt,
20
+ onClick = noop,
21
+ onZoom = noop,
22
+ url,
23
+ zooming = false,
24
+ }: SlideType): React.ReactElement {
25
+ const handlePinchingStop = ({state}: {state: any}) => {
26
+ const isZooming = state.scale > 1
27
+ onZoom(isZooming)
28
+ }
29
+
30
+ return (
31
+ <TransformWrapper
32
+ doubleClick={{ mode: 'reset' }}
33
+ initialScale={1}
34
+ onPinchingStop={handlePinchingStop}
35
+ panning={{ disabled: !zooming }}
36
+ >
37
+ <button
38
+ className="Slide"
39
+ onClick={onClick}
40
+ onDoubleClick={() => onZoom(false)}
41
+ tabIndex={-1}
42
+ >
43
+ <TransformComponent wrapperClass="TransformComponent">
44
+ <Image
45
+ alt={alt}
46
+ url={url}
47
+ zIndex={3}
48
+ />
49
+ </TransformComponent>
50
+ </button>
51
+ </TransformWrapper>
52
+ )
53
+ }
@@ -0,0 +1,35 @@
1
+ /* @flow */
2
+
3
+ import { noop } from 'lodash'
4
+ import React, { useState } from 'react'
5
+
6
+ import Slide from './Slide'
7
+
8
+ type SlidesType = {
9
+ urls: Array<string>,
10
+ current: number,
11
+ onChange: (index: number) => void,
12
+ onClick: (index: number) => void,
13
+ }
14
+
15
+ export default function Slides({
16
+ urls = [],
17
+ current = 0,
18
+ onChange = noop,
19
+ }: SlidesType): React.ReactElement {
20
+ const [zooming, setZooming] = useState(false)
21
+
22
+ const handleZoom = (isZooming: boolean) => setZooming(isZooming)
23
+ return (
24
+ <div
25
+ className="Slides"
26
+ >
27
+ <Slide
28
+ onClick={() => onChange(current)}
29
+ onZoom={handleZoom}
30
+ url={urls[current]}
31
+ zooming={zooming}
32
+ />
33
+ </div>
34
+ )
35
+ }
@@ -0,0 +1,39 @@
1
+ import React from 'react'
2
+ import { noop } from 'lodash'
3
+ import classnames from 'classnames'
4
+ import Image from '../../pb_image/_image'
5
+
6
+ type ThumbnailType = {
7
+ active?: boolean,
8
+ alt?: string,
9
+ onClick: () => void,
10
+ buttonRef?: React.RefObject<HTMLButtonElement>,
11
+ url: string,
12
+ width?: string,
13
+ }
14
+
15
+ export default function Thumbnail({
16
+ active = false,
17
+ alt,
18
+ width,
19
+ url,
20
+ onClick = noop,
21
+ buttonRef,
22
+ }: ThumbnailType): React.ReactElement {
23
+ const activeClasses = classnames('Thumbnail', { active })
24
+ return (
25
+ <button
26
+ className={classnames(activeClasses)}
27
+ onClick={onClick}
28
+ ref={buttonRef}
29
+ style={{ width }}
30
+ type="button"
31
+ >
32
+ <Image
33
+ alt={alt}
34
+ size="sm"
35
+ url={url}
36
+ />
37
+ </button>
38
+ )
39
+ }
@@ -0,0 +1,75 @@
1
+ import { noop } from 'lodash'
2
+ import classnames from 'classnames'
3
+ import React, { useLayoutEffect } from 'react'
4
+ import { useWindowSize } from '../hooks/useWindowSize'
5
+
6
+ import Thumbnail from './Thumbnail'
7
+
8
+ export const indexWithinBounds = (
9
+ current: number,
10
+ min: number,
11
+ max: number
12
+ ): number => {
13
+ if (current < min) return 0
14
+ if (current > max) return max
15
+ return current
16
+ }
17
+
18
+ type ThumbnailsType = {
19
+ current: number,
20
+ onChange: (index: number) => void,
21
+ urls: string[],
22
+ }
23
+
24
+ export default function Thumbnails({
25
+ current = 0,
26
+ onChange = noop,
27
+ urls = [],
28
+ }: ThumbnailsType): React.ReactElement {
29
+ const viewportSize = useWindowSize()
30
+ const thumbnailWidth = viewportSize.width / 8
31
+ const draggable = thumbnailWidth * urls.length > viewportSize.width
32
+ const shouldBeCentered = (thumbnailWidth * urls.length) < (viewportSize.width * 0.9)
33
+ const css = classnames('Thumbnails', { draggable }, { centered: shouldBeCentered })
34
+
35
+ const otherProps: { buttonRef?: React.RefObject<HTMLButtonElement> } = {}
36
+
37
+ const thumbnailsRef: React.RefObject<HTMLDivElement> = React.createRef()
38
+
39
+ useLayoutEffect(() => {
40
+ if (shouldBeCentered) return
41
+
42
+ const currentThumbnail = otherProps.buttonRef.current
43
+
44
+ const thumbWidth = currentThumbnail.clientWidth,
45
+ scrollLeft = thumbWidth * current,
46
+ firstThumb: HTMLButtonElement = thumbnailsRef.current.querySelector('.Thumbnail:first-child'),
47
+ lastThumb: HTMLButtonElement = thumbnailsRef.current.querySelector('.Thumbnail:last-child')
48
+
49
+ firstThumb.style.marginLeft = `${(thumbnailsRef.current?.clientWidth / 2) - (thumbWidth / 2)}px`
50
+ lastThumb.style.marginRight = `${(thumbnailsRef.current?.clientWidth / 2) - (thumbWidth / 2)}px`
51
+ thumbnailsRef.current?.scrollTo(scrollLeft, 0)
52
+ })
53
+
54
+ return (
55
+ <div
56
+ className={css}
57
+ ref={thumbnailsRef}
58
+ >
59
+ {urls.map((url, i) => {
60
+ const active = i === current
61
+ if (active) otherProps.buttonRef = React.createRef()
62
+ return (
63
+ <Thumbnail
64
+ active={active}
65
+ alt={i.toString()}
66
+ key={i}
67
+ onClick={() => onChange(i)}
68
+ url={url}
69
+ {...otherProps}
70
+ />
71
+ )
72
+ })}
73
+ </div>
74
+ )
75
+ }
@@ -0,0 +1,57 @@
1
+ /* eslint-disable jsx-control-statements/jsx-use-if-tag */
2
+ import { noop } from 'lodash'
3
+ import React, { useEffect } from 'react'
4
+
5
+ import Slides from './Slides'
6
+ import Thumbnails from './Thumbnails'
7
+
8
+ type CarouselType = {
9
+ initialPhoto?: string,
10
+ onClose?: () => void,
11
+ icon?: string,
12
+ iconSize?: number,
13
+ currentIndex: number,
14
+ photos: {
15
+ url: string,
16
+ thumbnail: string,
17
+ }[],
18
+ onChange: (index: number) => void,
19
+ onClick?: (index: number) => void,
20
+ }
21
+
22
+ export default function Carousel({
23
+ currentIndex,
24
+ photos,
25
+ onClick = noop,
26
+ onChange = noop,
27
+ }: CarouselType): React.ReactElement {
28
+ useEffect(() => {
29
+ document.body.style.overflow = 'hidden'
30
+
31
+ return () => {
32
+ document.body.style.overflow = 'initial'
33
+ }
34
+ }, [])
35
+
36
+ const handleChange = (index: number) => {
37
+ onChange(index)
38
+ }
39
+
40
+ return (
41
+ <div className="Lightbox">
42
+ <Slides
43
+ current={currentIndex}
44
+ onChange={handleChange}
45
+ onClick={onClick}
46
+ urls={photos.map((photo) => photo.url)}
47
+ />
48
+ {photos.length > 1 ? (
49
+ <Thumbnails
50
+ current={currentIndex}
51
+ onChange={handleChange}
52
+ urls={photos.map((photo) => photo.thumbnail)}
53
+ />
54
+ ) : null}
55
+ </div>
56
+ )
57
+ }
@@ -0,0 +1,115 @@
1
+ import React, { Fragment, useMemo, useRef, useState } from 'react'
2
+ import { useKbdControls } from './hooks/useKbdControls'
3
+ import classnames from 'classnames'
4
+ import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
5
+ import { globalProps } from '../utilities/globalProps'
6
+ import LightboxHeader from './_lightbox_header'
7
+ import { LightboxContext } from './_lightbox_context'
8
+ import { IconSizes } from '../pb_icon/_icon'
9
+
10
+ import Carousel from './Carousel/index'
11
+
12
+ type LightboxType = {
13
+ aria?: {[key: string]: string},
14
+ children: React.ReactNode[] | React.ReactNode | string,
15
+ className?: string,
16
+ data?: {[key: string]: string | number},
17
+ description?: string,
18
+ id?: string,
19
+ photos: [],
20
+ initialPhoto?: number,
21
+ onClose: () => void,
22
+ icon: string,
23
+ iconSize: IconSizes,
24
+ showCount?: boolean,
25
+ textRight?: string,
26
+ trigger?: string,
27
+ title?: string,
28
+ }
29
+
30
+ const Lightbox = (props: LightboxType): React.ReactNode => {
31
+ const {
32
+ aria = {},
33
+ children,
34
+ className,
35
+ data = {},
36
+ description,
37
+ id = '',
38
+ initialPhoto = 0,
39
+ photos,
40
+ onClose,
41
+ icon = 'times',
42
+ iconSize = '2x',
43
+ showCount = true,
44
+ textRight = 'All Photos',
45
+ title,
46
+ } = props
47
+ const [activePhoto, setActivePhoto] = useState(initialPhoto)
48
+
49
+ const ariaProps = buildAriaProps(aria)
50
+ const dataProps = buildDataProps(data)
51
+ const classes = classnames(
52
+ buildCss('pb_lightbox_kit'),
53
+ globalProps(props),
54
+ className
55
+ )
56
+
57
+ const handleOnSlide = (photoIndex: number) => {
58
+ setActivePhoto(photoIndex)
59
+ }
60
+
61
+ const photosMap = useMemo(() => photos.map((photo) => ({
62
+ url: photo,
63
+ thumbnail: photo,
64
+ })), [photos])
65
+
66
+ const api = {
67
+ onClose: onClose,
68
+ onArrowLeft: () => {
69
+ setActivePhoto(activePhoto > 0 ? activePhoto - 1 : 0)
70
+ },
71
+ onArrowRight: () => {
72
+ const nextPhoto = activePhoto < photos.length - 1 ? activePhoto + 1 : photos.length - 1
73
+ setActivePhoto(nextPhoto)
74
+ },
75
+ }
76
+ useKbdControls(api)
77
+
78
+ const lightboxRef: any = useRef()
79
+
80
+ const headerTextRight = showCount ? `${activePhoto + 1} / ${photos.length}` : textRight
81
+
82
+ return (
83
+ <Fragment>
84
+ <LightboxContext.Provider value={api}>
85
+ <div
86
+ {...ariaProps}
87
+ {...dataProps}
88
+ className={classes}
89
+ id={id}
90
+ ref={lightboxRef}
91
+ >
92
+ <div className="carousel">
93
+ <Lightbox.Header
94
+ icon={icon}
95
+ iconSize={iconSize}
96
+ text={description}
97
+ textRight={headerTextRight}
98
+ title={title}
99
+ />
100
+ {children}
101
+ <Carousel
102
+ currentIndex={activePhoto}
103
+ onChange={handleOnSlide}
104
+ photos={photosMap}
105
+ />
106
+ </div>
107
+ </div>
108
+ </LightboxContext.Provider>
109
+ </Fragment>
110
+ )
111
+ }
112
+
113
+ Lightbox.Header = LightboxHeader
114
+
115
+ export default Lightbox
@@ -0,0 +1,3 @@
1
+ import React from 'react'
2
+
3
+ export const LightboxContext = React.createContext({})