playbook_ui 14.12.0.pre.alpha.PBNTR720railscarddraggable5649 → 14.12.0.pre.alpha.PBNTR779railsdraggablecrosscontainer5863
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +2 -2
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +3 -4
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +3 -3
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_loading.html.erb +33 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_loading_rails.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_loading.md → _advanced_table_loading_react.md} +2 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_responsive.html.erb +38 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/index.js +9 -6
- data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +17 -3
- data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +15 -11
- data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +14 -3
- data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +10 -7
- data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +9 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.html.erb +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.rb +9 -0
- data/app/pb_kits/playbook/pb_avatar/_avatar.scss +14 -0
- data/app/pb_kits/playbook/pb_avatar/_avatar.tsx +11 -7
- data/app/pb_kits/playbook/pb_avatar/avatar.html.erb +6 -7
- data/app/pb_kits/playbook/pb_avatar/docs/_avatar_badge_component_overlay.jsx +9 -3
- data/app/pb_kits/playbook/pb_avatar/docs/_avatar_circle_icon_component_overlay.jsx +6 -2
- data/app/pb_kits/playbook/pb_button/button.rb +1 -1
- 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_date/_date.tsx +14 -4
- data/app/pb_kits/playbook/pb_date/docs/_date_default.jsx +2 -1
- data/app/pb_kits/playbook/pb_date/docs/_date_unstyled.jsx +13 -5
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_rails.html.erb +193 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_rails.md +1 -0
- data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -5
- data/app/pb_kits/playbook/pb_draggable/draggable_container.html.erb +2 -2
- data/app/pb_kits/playbook/pb_draggable/draggable_container.rb +3 -0
- data/app/pb_kits/playbook/pb_draggable/draggable_item.rb +2 -0
- data/app/pb_kits/playbook/pb_draggable/index.js +88 -16
- data/app/pb_kits/playbook/pb_file_upload/file_upload.html.erb +1 -6
- data/app/pb_kits/playbook/pb_filter/filter.html.erb +1 -5
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close.html.erb +58 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_auto_close_rails.md +3 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/index.js +7 -5
- data/app/pb_kits/playbook/pb_form_group/form_group.html.erb +1 -6
- data/app/pb_kits/playbook/pb_form_pill/form_pill.html.erb +1 -1
- data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +11 -7
- data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting.html.erb +11 -0
- data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting.jsx +22 -0
- data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting_rails.md +1 -0
- data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting_react.md +1 -0
- data/app/pb_kits/playbook/pb_home_address_street/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_home_address_street/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_home_address_street/home_address_street.rb +11 -2
- data/app/pb_kits/playbook/pb_table/docs/_table_with_background_kit.html.erb +6 -9
- data/app/pb_kits/playbook/pb_table/docs/_table_with_background_kit.jsx +6 -9
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_content.jsx +12 -8
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_content_rails.html.erb +52 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_content_rails.md +0 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows_rails.html.erb +52 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows_rails.md +3 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table_rails.html.erb +80 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table_rails.md +1 -0
- data/app/pb_kits/playbook/pb_table/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_table/styles/_desktop_collapse.scss +26 -0
- data/app/pb_kits/playbook/pb_table/styles/_mobile.scss +0 -1
- data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +25 -0
- data/app/pb_kits/playbook/pb_table/styles/_tablet_collapse.scss +25 -0
- data/app/pb_kits/playbook/pb_table/table_row.rb +1 -1
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +3 -1
- data/app/pb_kits/playbook/pb_user/_user.tsx +3 -0
- data/app/pb_kits/playbook/pb_user/docs/_user_light_weight.html.erb +42 -0
- data/app/pb_kits/playbook/pb_user/docs/_user_light_weight.jsx +59 -0
- data/app/pb_kits/playbook/pb_user/docs/_user_light_weight.md +2 -0
- data/app/pb_kits/playbook/pb_user/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_user/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_user/user.html.erb +1 -1
- data/app/pb_kits/playbook/pb_user/user.rb +1 -0
- data/app/pb_kits/playbook/pb_user/user.test.js +14 -0
- data/dist/chunks/_typeahead-W0hatdPs.js +36 -0
- data/dist/chunks/_weekday_stacked-C98LOqgG.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/dist/playbook.css +1 -1
- data/lib/playbook/pb_forms_global_props_helper.rb +136 -0
- data/lib/playbook/pb_forms_helper.rb +13 -4
- data/lib/playbook/version.rb +1 -1
- metadata +35 -6
- data/dist/chunks/_typeahead-BWwaAo_0.js +0 -36
- data/dist/chunks/_weekday_stacked-zyBCd1s8.js +0 -45
- /data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/{_fixed_confirmation_toast_auto_close.md → _fixed_confirmation_toast_auto_close_react.md} +0 -0
@@ -1,18 +1,19 @@
|
|
1
1
|
import React from "react";
|
2
2
|
import { Avatar } from 'playbook-ui'
|
3
3
|
|
4
|
-
const AvatarBadgeComponentOverlay = () => {
|
4
|
+
const AvatarBadgeComponentOverlay = (props) => {
|
5
5
|
return (
|
6
6
|
<div>
|
7
7
|
<Avatar
|
8
8
|
componentOverlay={{
|
9
9
|
component: "badge",
|
10
10
|
placement: "bottom-right",
|
11
|
-
text: "12"
|
11
|
+
text: "12",
|
12
12
|
}}
|
13
13
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
14
14
|
marginBottom="sm"
|
15
15
|
size="sm"
|
16
|
+
{...props}
|
16
17
|
/>
|
17
18
|
|
18
19
|
<Avatar
|
@@ -24,6 +25,8 @@ const AvatarBadgeComponentOverlay = () => {
|
|
24
25
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
25
26
|
marginBottom="sm"
|
26
27
|
size="md"
|
28
|
+
{...props}
|
29
|
+
|
27
30
|
/>
|
28
31
|
|
29
32
|
<Avatar
|
@@ -36,6 +39,8 @@ const AvatarBadgeComponentOverlay = () => {
|
|
36
39
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
37
40
|
marginBottom="sm"
|
38
41
|
size="lg"
|
42
|
+
{...props}
|
43
|
+
|
39
44
|
/>
|
40
45
|
|
41
46
|
<Avatar
|
@@ -48,7 +53,8 @@ const AvatarBadgeComponentOverlay = () => {
|
|
48
53
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
49
54
|
marginBottom="sm"
|
50
55
|
size="xl"
|
51
|
-
|
56
|
+
{...props}
|
57
|
+
/>
|
52
58
|
</div>
|
53
59
|
)
|
54
60
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import React from "react";
|
2
2
|
import { Avatar } from 'playbook-ui'
|
3
3
|
|
4
|
-
const AvatarCircleIconComponentOverlay = () => {
|
4
|
+
const AvatarCircleIconComponentOverlay = (props) => {
|
5
5
|
return (
|
6
6
|
<div>
|
7
7
|
<Avatar
|
@@ -14,6 +14,7 @@ const AvatarCircleIconComponentOverlay = () => {
|
|
14
14
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
15
15
|
marginBottom="sm"
|
16
16
|
size="sm"
|
17
|
+
{...props}
|
17
18
|
/>
|
18
19
|
|
19
20
|
<Avatar
|
@@ -26,6 +27,7 @@ const AvatarCircleIconComponentOverlay = () => {
|
|
26
27
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
27
28
|
marginBottom="sm"
|
28
29
|
size="md"
|
30
|
+
{...props}
|
29
31
|
/>
|
30
32
|
|
31
33
|
<Avatar
|
@@ -38,6 +40,7 @@ const AvatarCircleIconComponentOverlay = () => {
|
|
38
40
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
39
41
|
marginBottom="sm"
|
40
42
|
size="lg"
|
43
|
+
{...props}
|
41
44
|
/>
|
42
45
|
|
43
46
|
<Avatar
|
@@ -50,7 +53,8 @@ const AvatarCircleIconComponentOverlay = () => {
|
|
50
53
|
imageUrl="https://randomuser.me/api/portraits/men/44.jpg"
|
51
54
|
marginBottom="sm"
|
52
55
|
size="xl"
|
53
|
-
|
56
|
+
{...props}
|
57
|
+
/>
|
54
58
|
</div>
|
55
59
|
)
|
56
60
|
}
|
@@ -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.
|
@@ -14,6 +14,7 @@ type PbDateProps = {
|
|
14
14
|
alignment?: "left" | "center" | "right";
|
15
15
|
aria?: { [key: string]: string };
|
16
16
|
className?: string;
|
17
|
+
dark?: boolean;
|
17
18
|
data?: { [key: string]: string };
|
18
19
|
htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
|
19
20
|
id?: string;
|
@@ -29,6 +30,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
29
30
|
aria = {},
|
30
31
|
alignment = "left",
|
31
32
|
className,
|
33
|
+
dark = false,
|
32
34
|
data = {},
|
33
35
|
htmlOptions = {},
|
34
36
|
id,
|
@@ -56,7 +58,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
56
58
|
);
|
57
59
|
|
58
60
|
return (
|
59
|
-
<div
|
61
|
+
<div
|
60
62
|
{...ariaProps}
|
61
63
|
{...dataProps}
|
62
64
|
{...htmlProps}
|
@@ -93,7 +95,9 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
93
95
|
</>
|
94
96
|
: size == "md" || size == "lg"
|
95
97
|
? (
|
96
|
-
<Title
|
98
|
+
<Title
|
99
|
+
dark={dark}
|
100
|
+
size={4}
|
97
101
|
tag="h4"
|
98
102
|
>
|
99
103
|
{showIcon && (
|
@@ -127,6 +131,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
127
131
|
<>
|
128
132
|
{showIcon && (
|
129
133
|
<Caption className="pb_icon_kit_container"
|
134
|
+
dark={dark}
|
130
135
|
tag="span"
|
131
136
|
>
|
132
137
|
<Icon fixedWidth
|
@@ -138,15 +143,20 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
138
143
|
|
139
144
|
{showDayOfWeek && (
|
140
145
|
<>
|
141
|
-
<Caption
|
146
|
+
<Caption dark={dark}
|
147
|
+
tag="div">
|
148
|
+
{weekday}
|
149
|
+
</Caption>
|
142
150
|
<Caption color="light"
|
151
|
+
dark={dark}
|
143
152
|
tag="div"
|
144
153
|
text=" • "
|
145
154
|
/>
|
146
155
|
</>
|
147
156
|
)}
|
148
157
|
|
149
|
-
<Caption
|
158
|
+
<Caption dark={dark}
|
159
|
+
tag="span">
|
150
160
|
{month} {day}
|
151
161
|
{currentYear != year && <>{`, ${year}`}</>}
|
152
162
|
</Caption>
|
@@ -18,7 +18,7 @@ const DateDefault = (props) => {
|
|
18
18
|
value={"2012-08-03"}
|
19
19
|
{...props}
|
20
20
|
/>
|
21
|
-
<Caption>{"(Hyphenated Date)"}</Caption>
|
21
|
+
<Caption {...props}>{"(Hyphenated Date)"}</Caption>
|
22
22
|
</div>
|
23
23
|
|
24
24
|
<br />
|
@@ -56,6 +56,7 @@ const DateDefault = (props) => {
|
|
56
56
|
<Title
|
57
57
|
size={4}
|
58
58
|
text={"(Hyphenated Date)"}
|
59
|
+
{...props}
|
59
60
|
/>
|
60
61
|
</div>
|
61
62
|
|
@@ -4,7 +4,8 @@ import { Caption, Date as FormattedDate, Title } from 'playbook-ui'
|
|
4
4
|
const DateUnstyled = (props) => {
|
5
5
|
return (
|
6
6
|
<>
|
7
|
-
<Caption
|
7
|
+
<Caption {...props}
|
8
|
+
size="xs"
|
8
9
|
text="Basic unstyled example"
|
9
10
|
/>
|
10
11
|
<FormattedDate
|
@@ -15,10 +16,14 @@ const DateUnstyled = (props) => {
|
|
15
16
|
|
16
17
|
<br />
|
17
18
|
|
18
|
-
<Caption
|
19
|
+
<Caption {...props}
|
20
|
+
|
21
|
+
size="xs"
|
19
22
|
text="Example with wrapping typography kit"
|
20
23
|
/>
|
21
|
-
<Title
|
24
|
+
<Title {...props}
|
25
|
+
size={1}
|
26
|
+
>
|
22
27
|
<FormattedDate
|
23
28
|
unstyled
|
24
29
|
value={new Date('25 Dec 1995')}
|
@@ -28,10 +33,13 @@ const DateUnstyled = (props) => {
|
|
28
33
|
|
29
34
|
<br />
|
30
35
|
|
31
|
-
<Caption
|
36
|
+
<Caption {...props}
|
37
|
+
size="xs"
|
32
38
|
text="Example with icon + subcaption"
|
33
39
|
/>
|
34
|
-
<Caption
|
40
|
+
<Caption {...props}
|
41
|
+
size="xs"
|
42
|
+
>
|
35
43
|
<FormattedDate
|
36
44
|
showDayOfWeek
|
37
45
|
showIcon
|
@@ -0,0 +1,193 @@
|
|
1
|
+
<% content_for :helper_methods do %>
|
2
|
+
<% def badge_properties(container)
|
3
|
+
case container
|
4
|
+
when "To Do"
|
5
|
+
{ text: "queue", variant: "warning" }
|
6
|
+
when "In Progress"
|
7
|
+
{ text: "progress", variant: "primary" }
|
8
|
+
else
|
9
|
+
{ text: "done", variant: "success" }
|
10
|
+
end
|
11
|
+
end %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% containers = [
|
15
|
+
"To Do",
|
16
|
+
"In Progress",
|
17
|
+
"Done"
|
18
|
+
] %>
|
19
|
+
|
20
|
+
<% items_data = [
|
21
|
+
{
|
22
|
+
id: "11",
|
23
|
+
container: "To Do",
|
24
|
+
title: "Task 1",
|
25
|
+
description: "Bug fixes",
|
26
|
+
assignee_name: "Terry Miles",
|
27
|
+
assignee_img: "https://randomuser.me/api/portraits/men/44.jpg",
|
28
|
+
},
|
29
|
+
{
|
30
|
+
id: "12",
|
31
|
+
container: "To Do",
|
32
|
+
title: "Task 2",
|
33
|
+
description: "Documentation",
|
34
|
+
assignee_name: "Sophia Miles",
|
35
|
+
assignee_img: "https://randomuser.me/api/portraits/women/8.jpg",
|
36
|
+
},
|
37
|
+
{
|
38
|
+
id: "13",
|
39
|
+
container: "In Progress",
|
40
|
+
title: "Task 3",
|
41
|
+
description: "Add a variant",
|
42
|
+
assignee_name: "Alice Jones",
|
43
|
+
assignee_img: "https://randomuser.me/api/portraits/women/10.jpg",
|
44
|
+
},
|
45
|
+
{
|
46
|
+
id: "14",
|
47
|
+
container: "To Do",
|
48
|
+
title: "Task 4",
|
49
|
+
description: "Add jest tests",
|
50
|
+
assignee_name: "Mike James",
|
51
|
+
assignee_img: "https://randomuser.me/api/portraits/men/8.jpg",
|
52
|
+
},
|
53
|
+
{
|
54
|
+
id: "15",
|
55
|
+
container: "Done",
|
56
|
+
title: "Task 5",
|
57
|
+
description: "Alpha testing",
|
58
|
+
assignee_name: "James Guy",
|
59
|
+
assignee_img: "https://randomuser.me/api/portraits/men/18.jpg",
|
60
|
+
},
|
61
|
+
{
|
62
|
+
id: "16",
|
63
|
+
container: "In Progress",
|
64
|
+
title: "Task 6",
|
65
|
+
description: "Release",
|
66
|
+
assignee_name: "Sally Jones",
|
67
|
+
assignee_img: "https://randomuser.me/api/portraits/women/28.jpg",
|
68
|
+
},
|
69
|
+
] %>
|
70
|
+
|
71
|
+
<%= pb_rails("draggable", props: { initial_items: items_data }) do %>
|
72
|
+
<%= pb_rails("flex", props: { justify_content: "center" }) do %>
|
73
|
+
<% containers.each do |container| %>
|
74
|
+
<%= pb_rails("draggable/draggable_container", props: {
|
75
|
+
container: container,
|
76
|
+
width: "xs",
|
77
|
+
height: "xs",
|
78
|
+
padding: "sm",
|
79
|
+
data: { container: container }
|
80
|
+
}) do %>
|
81
|
+
<%= pb_rails("caption", props: { text_align: "center" }) do %><%= container %><% end %>
|
82
|
+
<%= pb_rails("flex", props: {align_items: "stretch", orientation: "column"}) do %>
|
83
|
+
<% items_data.select { |item| item[:container] == container }.each do |item| %>
|
84
|
+
<%= pb_rails("draggable/draggable_item", props: {
|
85
|
+
container: container,
|
86
|
+
drag_id: item[:id]
|
87
|
+
}) do %>
|
88
|
+
<%= pb_rails("card", props: { margin_bottom: "sm", padding: "sm"}) do %>
|
89
|
+
<%= pb_rails("flex", props: { justify: "between" }) do %>
|
90
|
+
<%= pb_rails("flex/flex_item") do %>
|
91
|
+
<%= pb_rails("flex") do %>
|
92
|
+
<%= pb_rails("avatar", props: {
|
93
|
+
image_url: item[:assignee_img],
|
94
|
+
name: item[:assignee_name],
|
95
|
+
size: "xxs"
|
96
|
+
}) %>
|
97
|
+
<%= pb_rails("title", props: {
|
98
|
+
padding_left: "xs",
|
99
|
+
size: 4,
|
100
|
+
text: item[:title]
|
101
|
+
}) %>
|
102
|
+
<% end %>
|
103
|
+
<% end %>
|
104
|
+
<%= pb_rails("badge", props: {
|
105
|
+
margin_left: "sm",
|
106
|
+
rounded: true,
|
107
|
+
text: badge_properties(container)[:text],
|
108
|
+
variant: badge_properties(container)[:variant],
|
109
|
+
data: {
|
110
|
+
pb_status_badge: true,
|
111
|
+
pb_tag_type: "badge"
|
112
|
+
}
|
113
|
+
}) %>
|
114
|
+
<% end %>
|
115
|
+
<%= pb_rails("body", props: { padding_top: "xs", text: item[:description] }) %>
|
116
|
+
<% end %>
|
117
|
+
<% end %>
|
118
|
+
<% end %>
|
119
|
+
<% end %>
|
120
|
+
<% end %>
|
121
|
+
<% end %>
|
122
|
+
<% end %>
|
123
|
+
<% end %>
|
124
|
+
|
125
|
+
<script>
|
126
|
+
const initBadgeUpdates = function() {
|
127
|
+
const updateBadge = function(container) {
|
128
|
+
switch (container) {
|
129
|
+
case 'To Do':
|
130
|
+
return { text: 'queue', variant: 'warning' };
|
131
|
+
case 'In Progress':
|
132
|
+
return { text: 'progress', variant: 'primary' };
|
133
|
+
case 'Done':
|
134
|
+
return { text: 'done', variant: 'success' };
|
135
|
+
default:
|
136
|
+
return { text: 'queue', variant: 'warning' };
|
137
|
+
}
|
138
|
+
};
|
139
|
+
|
140
|
+
let draggedElement = null;
|
141
|
+
let startContainer = null;
|
142
|
+
|
143
|
+
document.querySelectorAll('.pb_draggable_item').forEach(function(item) {
|
144
|
+
item.addEventListener('dragstart', function(event) {
|
145
|
+
draggedElement = event.target;
|
146
|
+
startContainer = draggedElement.closest('.pb_draggable_container');
|
147
|
+
});
|
148
|
+
});
|
149
|
+
|
150
|
+
document.querySelectorAll('.pb_draggable_container').forEach(function(container) {
|
151
|
+
container.addEventListener('drop', function(event) {
|
152
|
+
event.preventDefault();
|
153
|
+
|
154
|
+
if (draggedElement) {
|
155
|
+
setTimeout(function() {
|
156
|
+
const currentContainer = container;
|
157
|
+
|
158
|
+
if (currentContainer && startContainer && currentContainer !== startContainer) {
|
159
|
+
const containerData = currentContainer.getAttribute('data-container');
|
160
|
+
const badge = draggedElement.querySelector('[data-pb-status-badge]');
|
161
|
+
|
162
|
+
if (badge && containerData) {
|
163
|
+
const newProperties = updateBadge(containerData);
|
164
|
+
const span = badge.querySelector('span');
|
165
|
+
|
166
|
+
if (span) {
|
167
|
+
span.textContent = newProperties.text;
|
168
|
+
}
|
169
|
+
|
170
|
+
badge.classList.forEach(function(className) {
|
171
|
+
if (className.includes('pb_badge_kit_') || className === 'ml_sm') {
|
172
|
+
badge.classList.remove(className);
|
173
|
+
}
|
174
|
+
});
|
175
|
+
|
176
|
+
badge.className = `pb_badge_kit_${newProperties.variant}_rounded ml_sm`;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
draggedElement = null;
|
181
|
+
startContainer = null;
|
182
|
+
}, 50);
|
183
|
+
}
|
184
|
+
});
|
185
|
+
});
|
186
|
+
};
|
187
|
+
|
188
|
+
if (document.readyState === 'loading') {
|
189
|
+
document.addEventListener('DOMContentLoaded', initBadgeUpdates);
|
190
|
+
} else {
|
191
|
+
initBadgeUpdates();
|
192
|
+
}
|
193
|
+
</script>
|
@@ -0,0 +1 @@
|
|
1
|
+
The Draggable kit can also be used to achieve more complex, multiple container functionality as shown here. This complex usage requires the full subcomponent structure.
|