playbook_ui 14.13.0.pre.rc.0 → 14.13.0.pre.rc.1
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 +1 -0
- data/app/pb_kits/playbook/pb_copy_button/_copy_button.scss +3 -0
- data/app/pb_kits/playbook/pb_copy_button/_copy_button.tsx +92 -0
- data/app/pb_kits/playbook/pb_copy_button/copy_button.test.jsx +64 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_default.jsx +21 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_from.jsx +45 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_from.md +1 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/example.yml +8 -0
- data/app/pb_kits/playbook/pb_copy_button/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +3 -1
- data/dist/chunks/{_typeahead-BWwaAo_0.js → _typeahead-BIhRQo8Q.js} +3 -3
- data/dist/chunks/_weekday_stacked-DEajxTTC.js +45 -0
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +6 -0
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +12 -4
- data/dist/chunks/_weekday_stacked-zyBCd1s8.js +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec934923d24144acd3e8c89e5220ce814d3f88a3b46f65904d45720047aeceb1
|
4
|
+
data.tar.gz: 897bd9d197f2d3db6aa4ab309c9b84f05a42a6c10e3242aea2a2a3a70b19b990
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6d42bba771a7b47af28898bd32139f1b113781831cc6e870793b670082398ed440200c8e7d98f987cca69d4cb2ae551234cdfb91bf7b2dc115e69db639c052ab
|
7
|
+
data.tar.gz: 3f5e5f31e0817577b6b94118b5c641bcc749568726e47beabb853d9e6543b4680b206c8e3de9b883a6aec146ad8b292b4a66a794c84ea1d36adde7de3f23dffe
|
@@ -15,6 +15,7 @@
|
|
15
15
|
@import 'pb_circle_chart/circle_chart';
|
16
16
|
@import 'pb_circle_icon_button/circle_icon_button';
|
17
17
|
@import 'pb_collapsible/collapsible';
|
18
|
+
@import 'pb_copy_button/copy_button';
|
18
19
|
@import 'pb_contact/contact';
|
19
20
|
@import 'pb_currency/currency';
|
20
21
|
@import 'pb_dashboard_value/dashboard_value';
|
@@ -0,0 +1,92 @@
|
|
1
|
+
|
2
|
+
import React, { useState } from 'react'
|
3
|
+
import classnames from 'classnames'
|
4
|
+
import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
|
5
|
+
import { globalProps } from '../utilities/globalProps'
|
6
|
+
|
7
|
+
import Button from '../pb_button/_button'
|
8
|
+
import Tooltip from '../pb_tooltip/_tooltip'
|
9
|
+
|
10
|
+
type CopyButtonProps = {
|
11
|
+
aria?: { [key: string]: string },
|
12
|
+
className?: string,
|
13
|
+
data?: { [key: string]: string },
|
14
|
+
id?: string,
|
15
|
+
from?: string,
|
16
|
+
text?: string,
|
17
|
+
tooltipPlacement?: "top" | "right" | "bottom" | "left",
|
18
|
+
tooltipText?: string,
|
19
|
+
value?: string,
|
20
|
+
}
|
21
|
+
|
22
|
+
const CopyButton = (props: CopyButtonProps) => {
|
23
|
+
const {
|
24
|
+
aria = {},
|
25
|
+
className,
|
26
|
+
data = {},
|
27
|
+
from = '',
|
28
|
+
id,
|
29
|
+
text= 'Copy',
|
30
|
+
tooltipPlacement= 'bottom',
|
31
|
+
tooltipText = 'Copied!',
|
32
|
+
value = '',
|
33
|
+
} = props
|
34
|
+
|
35
|
+
const [copied, setCopied] = useState(false)
|
36
|
+
|
37
|
+
const ariaProps = buildAriaProps(aria)
|
38
|
+
const dataProps = buildDataProps(data)
|
39
|
+
const classes = classnames(buildCss('pb_copy_button_kit'), globalProps(props), className)
|
40
|
+
|
41
|
+
const copy = () => {
|
42
|
+
if (!from && !value) {
|
43
|
+
return
|
44
|
+
}
|
45
|
+
|
46
|
+
if (value) {
|
47
|
+
navigator.clipboard.writeText(value)
|
48
|
+
} else if (from) {
|
49
|
+
const copyElement = document.getElementById(from);
|
50
|
+
let copyText = copyElement?.innerText
|
51
|
+
|
52
|
+
if (copyElement instanceof HTMLTextAreaElement || copyElement instanceof HTMLInputElement) {
|
53
|
+
copyText = copyElement.value;
|
54
|
+
}
|
55
|
+
|
56
|
+
if (copyText) {
|
57
|
+
navigator.clipboard.writeText(copyText)
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
setCopied(true)
|
62
|
+
|
63
|
+
setTimeout(() => {
|
64
|
+
setCopied(false)
|
65
|
+
}, 1000);
|
66
|
+
}
|
67
|
+
|
68
|
+
return (
|
69
|
+
<div
|
70
|
+
{...ariaProps}
|
71
|
+
{...dataProps}
|
72
|
+
className={classes}
|
73
|
+
id={id}
|
74
|
+
>
|
75
|
+
<Tooltip
|
76
|
+
forceOpenTooltip={copied}
|
77
|
+
placement={tooltipPlacement}
|
78
|
+
showTooltip={false}
|
79
|
+
text={tooltipText}
|
80
|
+
>
|
81
|
+
<Button
|
82
|
+
icon='copy'
|
83
|
+
onClick={copy}
|
84
|
+
>
|
85
|
+
{ text }
|
86
|
+
</Button>
|
87
|
+
</Tooltip>
|
88
|
+
</div>
|
89
|
+
)
|
90
|
+
}
|
91
|
+
|
92
|
+
export default CopyButton
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { CopyButton } from 'playbook-ui'
|
3
|
+
import { ensureAccessible, renderKit, render, fireEvent, screen } from '../utilities/test-utils'
|
4
|
+
|
5
|
+
const props = {
|
6
|
+
data: { testid: 'default', value: 'copy' }
|
7
|
+
}
|
8
|
+
|
9
|
+
test('returns namespaced class name', () => {
|
10
|
+
const kit = renderKit(CopyButton, props)
|
11
|
+
expect(kit).toBeInTheDocument()
|
12
|
+
expect(kit).toHaveClass('pb_copy_button_kit')
|
13
|
+
})
|
14
|
+
|
15
|
+
it('should be accessible', async () => {
|
16
|
+
ensureAccessible(CopyButton, props)
|
17
|
+
})
|
18
|
+
|
19
|
+
// It's difficult to actually use navigator.clipboard.readText, so we mock
|
20
|
+
it('copies the value to clipboard and pastes it into an input', async () => {
|
21
|
+
Object.defineProperty(global, 'navigator', {
|
22
|
+
value: {
|
23
|
+
clipboard: {
|
24
|
+
writeText: jest.fn().mockResolvedValueOnce(undefined),
|
25
|
+
},
|
26
|
+
},
|
27
|
+
writable: true,
|
28
|
+
})
|
29
|
+
|
30
|
+
render(<CopyButton {...props} />)
|
31
|
+
|
32
|
+
const copyButton = screen.getByTestId('default')
|
33
|
+
fireEvent.click(copyButton)
|
34
|
+
|
35
|
+
await navigator.clipboard.writeText('copy')
|
36
|
+
|
37
|
+
expect(navigator.clipboard.writeText).toHaveBeenCalledWith("copy");
|
38
|
+
})
|
39
|
+
|
40
|
+
test('passes text and tooltip props to button', () => {
|
41
|
+
render(
|
42
|
+
<CopyButton
|
43
|
+
data={{ testid: 'text-test' }}
|
44
|
+
text={"text"}
|
45
|
+
tooltipPlacement="right"
|
46
|
+
tooltipText="Text copied!"
|
47
|
+
value="copy"
|
48
|
+
/>
|
49
|
+
)
|
50
|
+
|
51
|
+
const content = screen.getByText("text")
|
52
|
+
expect(content).toHaveTextContent("text")
|
53
|
+
|
54
|
+
const kit = screen.getByTestId('text-test')
|
55
|
+
const button = kit.querySelector('.pb_button_kit_primary_inline_enabled')
|
56
|
+
expect(button).toBeInTheDocument()
|
57
|
+
|
58
|
+
fireEvent.click(button)
|
59
|
+
const tooltipContent = screen.getByText("Text copied!")
|
60
|
+
expect(tooltipContent).toHaveTextContent("Text copied!")
|
61
|
+
|
62
|
+
const tooltip = kit.querySelector('.pb_tooltip_kit')
|
63
|
+
expect(tooltip).toBeInTheDocument()
|
64
|
+
})
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { CopyButton, Textarea } from 'playbook-ui'
|
3
|
+
|
4
|
+
const CopyButtonDefault = (props) => (
|
5
|
+
<div>
|
6
|
+
<CopyButton
|
7
|
+
{...props}
|
8
|
+
text="Copy Text"
|
9
|
+
tooltipPlacement="right"
|
10
|
+
tooltipText="Text copied!"
|
11
|
+
value="Playbook makes it easy to support bleeding edge, or legacy systems. Use Playbook’s 200+ components and end-to-end design language to create simple, intuitive and beautiful experiences with ease."
|
12
|
+
/>
|
13
|
+
|
14
|
+
<Textarea
|
15
|
+
{...props}
|
16
|
+
placeholder="Copy and paste here"
|
17
|
+
/>
|
18
|
+
</div>
|
19
|
+
)
|
20
|
+
|
21
|
+
export default CopyButtonDefault
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
import { CopyButton, Body, TextInput, Textarea } from 'playbook-ui'
|
3
|
+
|
4
|
+
const CopyButtonFrom = (props) => {
|
5
|
+
const [text, setText] = useState("Copy this text input text")
|
6
|
+
|
7
|
+
const handleChange = (event) => {
|
8
|
+
setText(event.target.value);
|
9
|
+
}
|
10
|
+
|
11
|
+
return (<div>
|
12
|
+
<Body id="body">Copy this body text!</Body>
|
13
|
+
<CopyButton
|
14
|
+
{...props}
|
15
|
+
from="body"
|
16
|
+
marginBottom="sm"
|
17
|
+
text="Copy Body text"
|
18
|
+
tooltipPlacement="right"
|
19
|
+
tooltipText="Body text copied!"
|
20
|
+
/>
|
21
|
+
|
22
|
+
<TextInput
|
23
|
+
{...props}
|
24
|
+
id="textinput"
|
25
|
+
onChange={handleChange}
|
26
|
+
value={text}
|
27
|
+
/>
|
28
|
+
<CopyButton
|
29
|
+
{...props}
|
30
|
+
from="textinput"
|
31
|
+
marginBottom="sm"
|
32
|
+
text="Copy Text Input"
|
33
|
+
tooltipPlacement="right"
|
34
|
+
tooltipText="Text input copied!"
|
35
|
+
/>
|
36
|
+
|
37
|
+
<Textarea
|
38
|
+
{...props}
|
39
|
+
placeholder="Copy and paste here"
|
40
|
+
/>
|
41
|
+
</div>
|
42
|
+
)
|
43
|
+
}
|
44
|
+
|
45
|
+
export default CopyButtonFrom
|
@@ -0,0 +1 @@
|
|
1
|
+
Provide an element's ID as the `from` parameter, and its text will be copied. If the element is an input, its `value` will be copied; otherwise, the `innerText` will be used. Additionally, if a `value` prop is provided, it will override the content from the `from` element and be copied instead.
|
@@ -32,6 +32,7 @@ type TooltipProps = {
|
|
32
32
|
position?: "absolute" | "fixed";
|
33
33
|
text: string,
|
34
34
|
showTooltip?: boolean,
|
35
|
+
forceOpenTooltip?: boolean,
|
35
36
|
} & GlobalProps
|
36
37
|
|
37
38
|
const Tooltip = forwardRef((props: TooltipProps, ref: ForwardedRef<unknown>): React.ReactElement => {
|
@@ -49,6 +50,7 @@ const Tooltip = forwardRef((props: TooltipProps, ref: ForwardedRef<unknown>): Re
|
|
49
50
|
text,
|
50
51
|
showTooltip = true,
|
51
52
|
zIndex,
|
53
|
+
forceOpenTooltip = false,
|
52
54
|
...rest
|
53
55
|
} = props
|
54
56
|
|
@@ -135,7 +137,7 @@ const Tooltip = forwardRef((props: TooltipProps, ref: ForwardedRef<unknown>): Re
|
|
135
137
|
>
|
136
138
|
{children}
|
137
139
|
</div>
|
138
|
-
{open && (
|
140
|
+
{(open || forceOpenTooltip) && (
|
139
141
|
<div
|
140
142
|
{...getFloatingProps({
|
141
143
|
className: `tooltip_tooltip ${placement} visible`,
|