playbook_ui 10.18.2 → 10.19.0.pre.lightbox
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +2 -0
- data/app/pb_kits/playbook/data/menu.yml +1 -0
- data/app/pb_kits/playbook/index.js +2 -1
- data/app/pb_kits/playbook/pb_body/_body.jsx +1 -1
- data/app/pb_kits/playbook/pb_body/_body_mixins.scss +2 -1
- data/app/pb_kits/playbook/pb_body/body.rb +1 -1
- data/app/pb_kits/playbook/pb_body/body.test.js +29 -0
- data/app/pb_kits/playbook/pb_body/docs/_body_light.html.erb +5 -0
- data/app/pb_kits/playbook/pb_body/docs/_body_light.jsx +5 -0
- data/app/pb_kits/playbook/pb_body/docs/_body_light.md +6 -0
- data/app/pb_kits/playbook/pb_caption/_caption.jsx +6 -6
- data/app/pb_kits/playbook/pb_caption/_caption.scss +6 -17
- data/app/pb_kits/playbook/pb_caption/_caption_mixin.scss +13 -3
- data/app/pb_kits/playbook/pb_caption/caption.rb +3 -5
- data/app/pb_kits/playbook/pb_caption/caption.test.js +29 -0
- data/app/pb_kits/playbook/pb_caption/docs/_caption_colors.html.erb +3 -0
- data/app/pb_kits/playbook/pb_caption/docs/_caption_colors.jsx +25 -0
- data/app/pb_kits/playbook/pb_caption/docs/_caption_colors.md +6 -0
- data/app/pb_kits/playbook/pb_caption/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_caption/docs/index.js +1 -2
- data/app/pb_kits/playbook/pb_lightbox/Carousel/Slide.jsx +53 -0
- data/app/pb_kits/playbook/pb_lightbox/Carousel/Slides.jsx +54 -0
- data/app/pb_kits/playbook/pb_lightbox/Carousel/Thumbnail.jsx +39 -0
- data/app/pb_kits/playbook/pb_lightbox/Carousel/Thumbnails.jsx +82 -0
- data/app/pb_kits/playbook/pb_lightbox/Carousel/index.jsx +54 -0
- data/app/pb_kits/playbook/pb_lightbox/Carousel/styles.scss +110 -0
- data/app/pb_kits/playbook/pb_lightbox/Carousel/useSlides.js +66 -0
- data/app/pb_kits/playbook/pb_lightbox/Carousel/useUnscrollableBody.js +11 -0
- data/app/pb_kits/playbook/pb_lightbox/_lightbox.jsx +81 -0
- data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_default.jsx +65 -0
- data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_default.md +1 -0
- data/app/pb_kits/playbook/pb_lightbox/docs/_lightbox_multiple.jsx +65 -0
- data/app/pb_kits/playbook/pb_lightbox/docs/example.yml +6 -0
- data/app/pb_kits/playbook/pb_lightbox/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_lightbox/hooks/useToggler.js +10 -0
- data/app/pb_kits/playbook/pb_lightbox/hooks/useVisibility.js +21 -0
- data/app/pb_kits/playbook/pb_lightbox/hooks/useWindowSize.js +25 -0
- data/app/pb_kits/playbook/pb_lightbox/lightbox.scss +92 -0
- data/app/pb_kits/playbook/pb_lightbox/lightbox.test.jsx +30 -0
- data/app/pb_kits/playbook/pb_nav/_bold_mixin.scss +22 -0
- data/app/pb_kits/playbook/pb_nav/_horizontal_nav.scss +17 -1
- data/app/pb_kits/playbook/pb_nav/_vertical_nav.scss +9 -2
- data/app/pb_kits/playbook/pb_nav/docs/_bold_horizontal_nav.html.erb +6 -0
- data/app/pb_kits/playbook/pb_nav/docs/_bold_horizontal_nav.jsx +39 -0
- data/app/pb_kits/playbook/pb_nav/docs/_bold_vertical_nav.html.erb +6 -0
- data/app/pb_kits/playbook/pb_nav/docs/_bold_vertical_nav.jsx +39 -0
- data/app/pb_kits/playbook/pb_nav/docs/_horizontal_nav.html.erb +1 -1
- data/app/pb_kits/playbook/pb_nav/docs/_subtle_nav.html.erb +1 -1
- data/app/pb_kits/playbook/pb_nav/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_nav/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_nav/nav.rb +1 -1
- data/app/pb_kits/playbook/pb_popover/docs/_popover_scroll_height.jsx +3 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_z_index.jsx +1 -0
- data/app/pb_kits/playbook/pb_text_input/_text_input.scss +62 -13
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.html.erb +21 -2
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.jsx +12 -3
- data/app/pb_kits/playbook/pb_title/_title.jsx +6 -4
- data/app/pb_kits/playbook/pb_title/_title.scss +5 -5
- data/app/pb_kits/playbook/pb_title/_title_mixin.scss +17 -0
- data/app/pb_kits/playbook/pb_title/docs/_title_colors.html.erb +4 -0
- data/app/pb_kits/playbook/pb_title/docs/_title_colors.jsx +37 -0
- data/app/pb_kits/playbook/pb_title/docs/_title_colors.md +6 -0
- data/app/pb_kits/playbook/pb_title/docs/_title_light.md +3 -0
- data/app/pb_kits/playbook/pb_title/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_title/docs/index.js +1 -1
- data/app/pb_kits/playbook/pb_title/title.html.erb +2 -3
- data/app/pb_kits/playbook/pb_title/title.rb +5 -4
- data/app/pb_kits/playbook/pb_title/title.test.js +29 -0
- data/app/pb_kits/playbook/playbook-doc.js +2 -0
- data/app/pb_kits/playbook/utilities/_line_height.scss +11 -0
- data/app/pb_kits/playbook/utilities/globalProps.js +7 -1
- data/lib/playbook/classnames.rb +1 -0
- data/lib/playbook/kit_base.rb +2 -0
- data/lib/playbook/line_height.rb +29 -0
- data/lib/playbook/version.rb +1 -1
- metadata +41 -13
- data/app/pb_kits/playbook/pb_caption/docs/_caption_example.html.erb +0 -3
- data/app/pb_kits/playbook/pb_caption/docs/_caption_example.jsx +0 -27
- data/app/pb_kits/playbook/pb_caption/docs/_caption_example.md +0 -1
- data/app/pb_kits/playbook/pb_caption/docs/_caption_variants.html.erb +0 -1
- data/app/pb_kits/playbook/pb_caption/docs/_caption_variants.jsx +0 -17
- data/app/pb_kits/playbook/pb_caption/docs/_caption_variants.md +0 -3
- data/app/pb_kits/playbook/pb_title/docs/_title_variants.html.erb +0 -1
- data/app/pb_kits/playbook/pb_title/docs/_title_variants.jsx +0 -19
- data/app/pb_kits/playbook/pb_title/docs/_title_variants.md +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: baa1f6f416384a560ac9d4e03d4aed20b4d01a980f4384c24a29a6a48ee19a60
|
4
|
+
data.tar.gz: 79ba5f8ef47057ac2e187c46676d559c59149afda9ecfb934debaab366104728
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edaa286cf749d9fdaa8b3ae854f59bc62681f0baffb90718b335a6774eec4133357f4eb7190b9f4545ec55b6cf41856052a0bc58ccedbd1d7c707b580654095a
|
7
|
+
data.tar.gz: a37e1263c2648e1bb032d49dc971871e7d5df0bd64091d4e61cdaf8e97f5df5915b2c6eb96f9b22508e3b3dc7c609206be70a979ccafd86616fa83b3cb005d38
|
@@ -47,6 +47,7 @@
|
|
47
47
|
@import 'pb_label_value/label_value';
|
48
48
|
@import 'pb_layout/layout';
|
49
49
|
@import 'pb_legend/legend';
|
50
|
+
@import 'pb_lightbox/lightbox';
|
50
51
|
@import 'pb_line_graph/line_graph';
|
51
52
|
@import 'pb_list/list';
|
52
53
|
@import 'pb_loading_inline/loading_inline';
|
@@ -98,4 +99,5 @@
|
|
98
99
|
@import './utilities/positioning';
|
99
100
|
@import './utilities/number_spacing';
|
100
101
|
@import './utilities/shadow';
|
102
|
+
@import './utilities/line_height';
|
101
103
|
@import './utilities/display';
|
@@ -4,7 +4,6 @@ import 'lazysizes/plugins/attrchange/ls.attrchange'
|
|
4
4
|
import 'lazysizes'
|
5
5
|
|
6
6
|
// vvv React Component JSX Imports from the React Kits vvv
|
7
|
-
export { default as Walkthrough } from './pb_walkthrough/_walkthrough'
|
8
7
|
export { default as Avatar } from './pb_avatar/_avatar'
|
9
8
|
export { default as AvatarActionButton } from './pb_avatar_action_button/_avatar_action_button'
|
10
9
|
export { default as Background } from './pb_background/_background'
|
@@ -55,6 +54,7 @@ export { default as Layout } from './pb_layout/_layout'
|
|
55
54
|
export { default as Legend } from './pb_legend/_legend'
|
56
55
|
export { default as LineGraph } from './pb_line_graph/_line_graph'
|
57
56
|
export { default as List } from './pb_list/_list'
|
57
|
+
export { default as Lightbox } from './pb_lightbox/_lightbox'
|
58
58
|
export { default as ListItem } from './pb_list/_list_item'
|
59
59
|
export { default as LoadingInline } from './pb_loading_inline/_loading_inline'
|
60
60
|
export { default as Message } from './pb_message/_message'
|
@@ -101,6 +101,7 @@ export { default as Toggle } from './pb_toggle/_toggle'
|
|
101
101
|
export { default as Typeahead } from './pb_typeahead/_typeahead'
|
102
102
|
export { default as User } from './pb_user/_user'
|
103
103
|
export { default as UserBadge } from './pb_user_badge/_user_badge'
|
104
|
+
export { default as Walkthrough } from './pb_walkthrough/_walkthrough'
|
104
105
|
export { default as WeekdayStacked } from './pb_weekday_stacked/_weekday_stacked'
|
105
106
|
// ^^^ React Component JSX Imports from the React Kits ^^^
|
106
107
|
|
@@ -12,7 +12,7 @@ type BodyProps = {
|
|
12
12
|
aria?: object,
|
13
13
|
className?: string,
|
14
14
|
children?: array<React.ReactChild>,
|
15
|
-
color?: 'default' | 'light' | 'lighter',
|
15
|
+
color?: 'default' | 'light' | 'lighter' | 'link',
|
16
16
|
dark?: boolean,
|
17
17
|
data?: object,
|
18
18
|
highlightedText?: array<string>,
|
@@ -6,6 +6,7 @@ $pb_body_colors: (
|
|
6
6
|
default: $text_lt_default,
|
7
7
|
light: $text_lt_light,
|
8
8
|
lighter: $text_lt_lighter,
|
9
|
+
link: $primary,
|
9
10
|
);
|
10
11
|
|
11
12
|
$pb_dark_body_colors: (
|
@@ -63,4 +64,4 @@ $pb_body_status: (
|
|
63
64
|
|
64
65
|
@mixin pb_body_positive {
|
65
66
|
@include pb_body($success);
|
66
|
-
}
|
67
|
+
}
|
@@ -4,7 +4,7 @@ module Playbook
|
|
4
4
|
module PbBody
|
5
5
|
class Body < Playbook::KitBase
|
6
6
|
prop :color, type: Playbook::Props::Enum,
|
7
|
-
values: %w[default light lighter],
|
7
|
+
values: %w[default light lighter link],
|
8
8
|
default: "default"
|
9
9
|
prop :status, type: Playbook::Props::Enum,
|
10
10
|
values: %w[neutral negative positive],
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { render, screen } from '../utilities/test-utils'
|
3
|
+
|
4
|
+
import Body from './_body'
|
5
|
+
|
6
|
+
test('returns namespaced class name', () => {
|
7
|
+
render(
|
8
|
+
<Body
|
9
|
+
data={{ testid: 'primary-test' }}
|
10
|
+
text="Test colors"
|
11
|
+
/>
|
12
|
+
)
|
13
|
+
|
14
|
+
const kit = screen.getByTestId('primary-test')
|
15
|
+
expect(kit).toHaveClass('pb_body_kit')
|
16
|
+
})
|
17
|
+
|
18
|
+
test('with colors', () => {
|
19
|
+
render(
|
20
|
+
<Body
|
21
|
+
color="success"
|
22
|
+
data={{ testid: 'primary-test' }}
|
23
|
+
text="Test colors"
|
24
|
+
/>
|
25
|
+
)
|
26
|
+
|
27
|
+
const kit = screen.getByTestId('primary-test')
|
28
|
+
expect(kit).toHaveClass('pb_body_kit_success')
|
29
|
+
})
|
@@ -0,0 +1,6 @@
|
|
1
|
+
##### Prop
|
2
|
+
This kit uses `default` color by default, and can be replaced with colors below:
|
3
|
+
|
4
|
+
* `light` `lighter` `success` `error` `link`
|
5
|
+
|
6
|
+
- These colors are not for standard usage. You can use the color prop to make fixes if colors are not appearing properly, but consult your UX team members if you are deciding to implement it
|
@@ -3,33 +3,33 @@
|
|
3
3
|
import React from 'react'
|
4
4
|
import classnames from 'classnames'
|
5
5
|
import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
|
6
|
-
import { globalProps } from '../utilities/globalProps.js'
|
6
|
+
import { deprecatedProps, globalProps } from '../utilities/globalProps.js'
|
7
7
|
|
8
8
|
type CaptionProps = {
|
9
9
|
aria?: object,
|
10
|
-
className?: string,
|
11
10
|
children: array<React.ReactNode> | React.ReactNode,
|
11
|
+
className?: string,
|
12
|
+
color?: "default" | "light" | "lighter" | "success" | "error" | "link",
|
12
13
|
data?: object,
|
13
14
|
id?: string,
|
14
15
|
size?: "xs" | "sm" | "md" | "lg" | "xl",
|
15
16
|
tag?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div" | "caption",
|
16
17
|
text?: string,
|
17
18
|
variant?: null | "link",
|
18
|
-
color?: "default" | "link" | "light",
|
19
19
|
};
|
20
20
|
|
21
21
|
const Caption = (props: CaptionProps) => {
|
22
|
+
if (props.variant) deprecatedProps('Title', ['variant']) //variant prop is deprecated, use color instead
|
22
23
|
const {
|
23
24
|
aria = {},
|
24
|
-
className,
|
25
25
|
children,
|
26
|
+
className,
|
26
27
|
color,
|
27
28
|
data = {},
|
28
29
|
id,
|
29
30
|
size = 'md',
|
30
31
|
tag = 'div',
|
31
32
|
text,
|
32
|
-
variant = null,
|
33
33
|
} = props
|
34
34
|
const tagOptions = [
|
35
35
|
'h1',
|
@@ -48,7 +48,7 @@ const Caption = (props: CaptionProps) => {
|
|
48
48
|
const ariaProps = buildAriaProps(aria)
|
49
49
|
const dataProps = buildDataProps(data)
|
50
50
|
const css = classnames(
|
51
|
-
buildCss('pb_caption_kit', size,
|
51
|
+
buildCss('pb_caption_kit', size, color),
|
52
52
|
globalProps(props),
|
53
53
|
className,
|
54
54
|
)
|
@@ -10,26 +10,15 @@
|
|
10
10
|
|
11
11
|
&[class^="pb_caption_kit_xs"] {
|
12
12
|
@include caption_xs;
|
13
|
-
&[class*="_link"] {
|
14
|
-
color: $primary;}
|
15
13
|
}
|
16
14
|
|
17
|
-
|
18
|
-
color: $text_lt_light;
|
19
|
-
}
|
20
|
-
|
21
|
-
&[class*="default"] {
|
22
|
-
color: $text_lt_default;
|
23
|
-
}
|
24
|
-
|
25
|
-
&[class*="link"] {
|
26
|
-
color: $primary;
|
27
|
-
}
|
15
|
+
@include pb_caption_kit_colors;
|
28
16
|
|
29
|
-
|
30
|
-
@
|
31
|
-
|
32
|
-
|
17
|
+
&.dark {
|
18
|
+
@include caption_dark;
|
19
|
+
@each $name, $color in $pb_dark_caption_colors {
|
20
|
+
&[class*="_#{$name}"] {
|
21
|
+
color: $color;
|
33
22
|
}
|
34
23
|
}
|
35
24
|
}
|
@@ -4,13 +4,16 @@
|
|
4
4
|
$pb_caption_colors: (
|
5
5
|
default: $text_lt_default,
|
6
6
|
light: $text_lt_light,
|
7
|
-
link: $primary
|
7
|
+
link: $primary,
|
8
|
+
lighter: $text_lt_lighter,
|
9
|
+
success: $success,
|
10
|
+
error: $error,
|
8
11
|
);
|
9
12
|
|
10
13
|
$pb_dark_caption_colors: (
|
11
|
-
default:
|
14
|
+
default: $text_dk_default,
|
12
15
|
light: $text_dk_light,
|
13
|
-
link: $primary
|
16
|
+
link: $primary,
|
14
17
|
);
|
15
18
|
|
16
19
|
|
@@ -39,3 +42,10 @@ $pb_dark_caption_colors: (
|
|
39
42
|
@mixin caption_dark {
|
40
43
|
color: $text_dk_light;
|
41
44
|
}
|
45
|
+
@mixin pb_caption_kit_colors {
|
46
|
+
@each $name, $color in $pb_caption_colors {
|
47
|
+
&[class*="#{$name}"] {
|
48
|
+
color: $color
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
@@ -10,16 +10,14 @@ module Playbook
|
|
10
10
|
values: %w[h1 h2 h3 h4 h5 h6 p span div caption],
|
11
11
|
default: "div"
|
12
12
|
prop :text
|
13
|
-
prop :variant,
|
14
|
-
values: [nil, "link"],
|
15
|
-
default: nil
|
13
|
+
prop :variant, deprecated: true
|
16
14
|
|
17
15
|
prop :color, type: Playbook::Props::Enum,
|
18
|
-
values: [nil, "light", "
|
16
|
+
values: [nil, "default", "light", "lighter", "success", "error", "link"],
|
19
17
|
default: nil
|
20
18
|
|
21
19
|
def classname
|
22
|
-
generate_classname("pb_caption_kit", size,
|
20
|
+
generate_classname("pb_caption_kit", size, color)
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { render, screen } from '../utilities/test-utils'
|
3
|
+
|
4
|
+
import Caption from './_caption'
|
5
|
+
|
6
|
+
test('returns namespaced class name', () => {
|
7
|
+
render(
|
8
|
+
<Caption
|
9
|
+
data={{ testid: 'primary-test' }}
|
10
|
+
text="Test colors"
|
11
|
+
/>
|
12
|
+
)
|
13
|
+
|
14
|
+
const kit = screen.getByTestId('primary-test')
|
15
|
+
expect(kit).toHaveClass('pb_caption_kit_md')
|
16
|
+
})
|
17
|
+
|
18
|
+
test('with colors', () => {
|
19
|
+
render(
|
20
|
+
<Caption
|
21
|
+
color="success"
|
22
|
+
data={{ testid: 'primary-test' }}
|
23
|
+
text="Test colors"
|
24
|
+
/>
|
25
|
+
)
|
26
|
+
|
27
|
+
const kit = screen.getByTestId('primary-test')
|
28
|
+
expect(kit).toHaveClass('pb_caption_kit_md_success')
|
29
|
+
})
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { Caption } from '../../'
|
3
|
+
|
4
|
+
const CaptionColors = (props) => {
|
5
|
+
return (
|
6
|
+
<div>
|
7
|
+
<Caption
|
8
|
+
text="Test colors"
|
9
|
+
{...props}
|
10
|
+
/>
|
11
|
+
<Caption
|
12
|
+
color="success"
|
13
|
+
text="Test colors"
|
14
|
+
{...props}
|
15
|
+
/>
|
16
|
+
<Caption
|
17
|
+
color="link"
|
18
|
+
text="Test colors"
|
19
|
+
{...props}
|
20
|
+
/>
|
21
|
+
</div>
|
22
|
+
)
|
23
|
+
}
|
24
|
+
|
25
|
+
export default CaptionColors
|
@@ -0,0 +1,6 @@
|
|
1
|
+
##### Prop
|
2
|
+
Caption kit will use `light` color by default. Other available colors are:
|
3
|
+
|
4
|
+
* `default` `lighter` `success` `error` `link`
|
5
|
+
|
6
|
+
- These colors are not for standard usage. You can use the color prop to make fixes if colors are not appearing properly, but consult your UX team members if you are deciding to implement it
|
@@ -2,9 +2,9 @@ examples:
|
|
2
2
|
rails:
|
3
3
|
- caption_light: Default
|
4
4
|
- caption_block: Block
|
5
|
-
-
|
5
|
+
- caption_colors: Colors
|
6
6
|
|
7
7
|
react:
|
8
8
|
- caption_light: Default
|
9
9
|
- caption_block: Block
|
10
|
-
-
|
10
|
+
- caption_colors: Colors
|
@@ -1,4 +1,3 @@
|
|
1
1
|
export { default as CaptionLight } from './_caption_light.jsx'
|
2
|
-
export { default as
|
2
|
+
export { default as CaptionColors } from './_caption_colors.jsx'
|
3
3
|
export { default as CaptionBlock } from './_caption_block.jsx'
|
4
|
-
export { default as CaptionExample } from './_caption_example.jsx'
|
@@ -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
|
+
|
7
|
+
import styles from './styles.scss'
|
8
|
+
|
9
|
+
type SlideType = {
|
10
|
+
alt: string,
|
11
|
+
current: number,
|
12
|
+
onClick: () => void,
|
13
|
+
onChange: (index: number) => void,
|
14
|
+
onZoom: (zoom: number) => void,
|
15
|
+
zooming: boolean,
|
16
|
+
url: string,
|
17
|
+
}
|
18
|
+
|
19
|
+
export default function Slide({
|
20
|
+
alt,
|
21
|
+
onClick = noop,
|
22
|
+
onZoom = noop,
|
23
|
+
url,
|
24
|
+
zooming = false,
|
25
|
+
}: SlideType) {
|
26
|
+
const handlePinchingStop = (e) => {
|
27
|
+
const isZooming = e.state.scale > 1
|
28
|
+
onZoom(isZooming)
|
29
|
+
}
|
30
|
+
|
31
|
+
return (
|
32
|
+
<TransformWrapper
|
33
|
+
doubleClick={{ mode: 'reset' }}
|
34
|
+
initialScale={1}
|
35
|
+
onPinchingStop={handlePinchingStop}
|
36
|
+
panning={{ disabled: !zooming }}
|
37
|
+
>
|
38
|
+
<button
|
39
|
+
className={styles.Slide}
|
40
|
+
onClick={onClick}
|
41
|
+
onDoubleClick={() => onZoom(false)}
|
42
|
+
tabIndex={-1}
|
43
|
+
>
|
44
|
+
<TransformComponent className={styles.TransformComponent}>
|
45
|
+
<img
|
46
|
+
alt={alt}
|
47
|
+
src={url}
|
48
|
+
/>
|
49
|
+
</TransformComponent>
|
50
|
+
</button>
|
51
|
+
</TransformWrapper>
|
52
|
+
)
|
53
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import { noop } from 'lodash'
|
4
|
+
import { motion } from 'framer-motion/dist/framer-motion'
|
5
|
+
import React, { useState } from 'react'
|
6
|
+
|
7
|
+
import Slide from './Slide'
|
8
|
+
import styles from './styles.scss'
|
9
|
+
import useSlides from './useSlides'
|
10
|
+
|
11
|
+
type SlidesType = {
|
12
|
+
urls: Array<string>,
|
13
|
+
current: number,
|
14
|
+
onChange: (index: number) => void,
|
15
|
+
onClick: (index: number) => void,
|
16
|
+
}
|
17
|
+
|
18
|
+
export default function Slides({
|
19
|
+
urls = [],
|
20
|
+
current = 0,
|
21
|
+
onClick = noop,
|
22
|
+
onChange = noop,
|
23
|
+
}: SlidesType) {
|
24
|
+
const [zooming, setZooming] = useState(false)
|
25
|
+
const { controls, dragConstraints, handleDragEnd } = useSlides({
|
26
|
+
current,
|
27
|
+
pagesCount: urls.length,
|
28
|
+
onChange,
|
29
|
+
})
|
30
|
+
|
31
|
+
const handleZoom = (isZooming) => setZooming(isZooming)
|
32
|
+
|
33
|
+
return (
|
34
|
+
<motion.div
|
35
|
+
animate={controls}
|
36
|
+
className={styles.Slides}
|
37
|
+
drag={!zooming && 'x'}
|
38
|
+
dragConstraints={dragConstraints}
|
39
|
+
dragElastic={0.05}
|
40
|
+
onDragEnd={handleDragEnd}
|
41
|
+
transition={{ type: 'spring', bounce: 0 }}
|
42
|
+
>
|
43
|
+
{urls.map((url, i) => (
|
44
|
+
<Slide
|
45
|
+
key={i}
|
46
|
+
onClick={() => onClick(i)}
|
47
|
+
onZoom={handleZoom}
|
48
|
+
url={url}
|
49
|
+
zooming={zooming}
|
50
|
+
/>
|
51
|
+
))}
|
52
|
+
</motion.div>
|
53
|
+
)
|
54
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import React from 'react'
|
4
|
+
import { noop } from 'lodash'
|
5
|
+
import classnames from 'classnames'
|
6
|
+
import Image from '../../pb_image/_image'
|
7
|
+
|
8
|
+
import styles from './styles.scss'
|
9
|
+
|
10
|
+
type ThumbnailType = {
|
11
|
+
active?: boolean,
|
12
|
+
alt?: string,
|
13
|
+
onClick: () => void,
|
14
|
+
url: string,
|
15
|
+
width?: string,
|
16
|
+
}
|
17
|
+
|
18
|
+
export default function Thumbnail({
|
19
|
+
active = false,
|
20
|
+
alt,
|
21
|
+
width,
|
22
|
+
url,
|
23
|
+
onClick = noop,
|
24
|
+
}: ThumbnailType) {
|
25
|
+
return (
|
26
|
+
<button
|
27
|
+
className={classnames(styles.Thumbnail, { [styles.active]: active })}
|
28
|
+
onClick={onClick}
|
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,82 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import { noop } from 'lodash'
|
4
|
+
import classnames from 'classnames'
|
5
|
+
import React, { useEffect } from 'react'
|
6
|
+
import { motion, useAnimation } from 'framer-motion/dist/framer-motion'
|
7
|
+
import { useWindowSize } from '../hooks/useWindowSize'
|
8
|
+
|
9
|
+
import Thumbnail from './Thumbnail'
|
10
|
+
|
11
|
+
import styles from './styles.scss'
|
12
|
+
|
13
|
+
export const indexWithinBounds = (
|
14
|
+
current: number,
|
15
|
+
min: number,
|
16
|
+
max: number
|
17
|
+
): number => {
|
18
|
+
if (current < min) return 0
|
19
|
+
if (current > max) return max
|
20
|
+
return current
|
21
|
+
}
|
22
|
+
|
23
|
+
type ThumbnailsType = {
|
24
|
+
current: number,
|
25
|
+
onChange: () => null,
|
26
|
+
urls: [],
|
27
|
+
}
|
28
|
+
|
29
|
+
export default function Thumbnails({
|
30
|
+
current = 0,
|
31
|
+
onChange = noop,
|
32
|
+
urls = [],
|
33
|
+
}: ThumbnailsType) {
|
34
|
+
const controls = useAnimation()
|
35
|
+
const viewportSize = useWindowSize()
|
36
|
+
const thumbnailWidth = viewportSize.width / 8
|
37
|
+
const draggable = thumbnailWidth * urls.length > viewportSize.width
|
38
|
+
const css = classnames(styles.Thumbnails, {
|
39
|
+
[styles.draggable]: draggable,
|
40
|
+
})
|
41
|
+
const dragConstraints = {
|
42
|
+
left: -1 * (thumbnailWidth * urls.length - viewportSize.width),
|
43
|
+
right: 0,
|
44
|
+
}
|
45
|
+
|
46
|
+
const modifyTarget = (target) => {
|
47
|
+
const nextIndex = Math.round(Math.abs(target) / thumbnailWidth)
|
48
|
+
const snapTargetIndex = indexWithinBounds(nextIndex, 0, urls.length)
|
49
|
+
const snapTarget = snapTargetIndex * thumbnailWidth
|
50
|
+
const direction = Math.sign(target)
|
51
|
+
return direction * snapTarget
|
52
|
+
}
|
53
|
+
|
54
|
+
useEffect(() => {
|
55
|
+
if (draggable) {
|
56
|
+
const x = Math.max(-current * thumbnailWidth, dragConstraints.left)
|
57
|
+
controls.start({ x })
|
58
|
+
}
|
59
|
+
}, [controls, current, draggable, dragConstraints.left, thumbnailWidth])
|
60
|
+
|
61
|
+
return (
|
62
|
+
<motion.div
|
63
|
+
animate={controls}
|
64
|
+
className={css}
|
65
|
+
drag={draggable && 'x'}
|
66
|
+
dragConstraints={dragConstraints}
|
67
|
+
dragElastic={0.05}
|
68
|
+
dragTransition={{ modifyTarget }}
|
69
|
+
transition={{ type: 'spring', bounce: 0 }}
|
70
|
+
>
|
71
|
+
{urls.map((url, i) => (
|
72
|
+
<Thumbnail
|
73
|
+
active={i === current}
|
74
|
+
alt={i}
|
75
|
+
key={i}
|
76
|
+
onClick={() => onChange(i)}
|
77
|
+
url={url}
|
78
|
+
/>
|
79
|
+
))}
|
80
|
+
</motion.div>
|
81
|
+
)
|
82
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/* eslint-disable jsx-control-statements/jsx-use-if-tag */
|
2
|
+
/* @flow */
|
3
|
+
|
4
|
+
import { noop } from 'lodash'
|
5
|
+
import React, { useState } from 'react'
|
6
|
+
|
7
|
+
import Slides from './Slides'
|
8
|
+
import Thumbnails from './Thumbnails'
|
9
|
+
import useUnscrollableBody from './useUnscrollableBody'
|
10
|
+
|
11
|
+
import styles from './styles.scss'
|
12
|
+
|
13
|
+
type CarouselType = {
|
14
|
+
initialPhoto: string,
|
15
|
+
onClose: Function,
|
16
|
+
icon: string,
|
17
|
+
iconSize: number,
|
18
|
+
current: number,
|
19
|
+
photos: Array<string>,
|
20
|
+
onChange: (index: number) => void,
|
21
|
+
onClick: (index: number) => void,
|
22
|
+
}
|
23
|
+
|
24
|
+
export default function Carousel({
|
25
|
+
current = 0,
|
26
|
+
photos,
|
27
|
+
onClick = noop,
|
28
|
+
onChange = noop,
|
29
|
+
}: CarouselType) {
|
30
|
+
useUnscrollableBody()
|
31
|
+
const [currentIndex, setCurrentIndex] = useState(current)
|
32
|
+
const handleChange = (index) => {
|
33
|
+
setCurrentIndex(index)
|
34
|
+
onChange(index)
|
35
|
+
}
|
36
|
+
|
37
|
+
return (
|
38
|
+
<div className={styles.Lightbox}>
|
39
|
+
<Slides
|
40
|
+
current={currentIndex}
|
41
|
+
onChange={handleChange}
|
42
|
+
onClick={onClick}
|
43
|
+
urls={photos.map((photo) => photo.url)}
|
44
|
+
/>
|
45
|
+
{photos.length > 1 ? (
|
46
|
+
<Thumbnails
|
47
|
+
current={currentIndex}
|
48
|
+
onChange={handleChange}
|
49
|
+
urls={photos.map((photo) => photo.thumbnail)}
|
50
|
+
/>
|
51
|
+
) : null}
|
52
|
+
</div>
|
53
|
+
)
|
54
|
+
}
|