playbook_ui 14.13.0.pre.alpha.play1834depupdatesass6024 → 14.13.0.pre.alpha.play1851checkboxreacthook6083

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_checkbox/_checkbox.tsx +17 -8
  3. data/app/pb_kits/playbook/pb_checkbox/checkbox.test.js +16 -0
  4. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_react_hook.jsx +69 -0
  5. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_react_hook.md +1 -0
  6. data/app/pb_kits/playbook/pb_checkbox/docs/example.yml +2 -1
  7. data/app/pb_kits/playbook/pb_checkbox/docs/index.js +1 -0
  8. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +3 -1
  9. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_default.html.erb +1 -2
  10. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_sizes.html.erb +27 -0
  11. data/app/pb_kits/playbook/pb_icon_button/docs/example.yml +1 -3
  12. data/app/pb_kits/playbook/pb_icon_button/icon_button.html.erb +1 -1
  13. data/app/pb_kits/playbook/pb_icon_button/icon_button.rb +3 -0
  14. data/app/pb_kits/playbook/pb_table/docs/_table_with_clickable_rows.html.erb +47 -0
  15. data/app/pb_kits/playbook/pb_table/docs/_table_with_clickable_rows.jsx +88 -0
  16. data/app/pb_kits/playbook/pb_table/docs/_table_with_clickable_rows.md +1 -0
  17. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +96 -0
  18. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.jsx +101 -0
  19. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.md +1 -0
  20. data/app/pb_kits/playbook/pb_table/docs/example.yml +4 -0
  21. data/app/pb_kits/playbook/pb_table/docs/index.js +3 -1
  22. data/dist/chunks/{_typeahead-DQTwAd_2.js → _typeahead-CR2Xkt-o.js} +2 -2
  23. data/dist/chunks/_weekday_stacked-9LU-xxnS.js +45 -0
  24. data/dist/chunks/vendor.js +1 -1
  25. data/dist/playbook-doc.js +1 -1
  26. data/dist/playbook-rails-react-bindings.js +1 -1
  27. data/dist/playbook-rails.js +1 -1
  28. data/lib/playbook/version.rb +1 -1
  29. metadata +13 -4
  30. data/dist/chunks/_weekday_stacked-CnPEqV7l.js +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eaae4c0710eed5f130a25be20f2b53abeb9c0e8411e98a2fea634d1d36ab4441
4
- data.tar.gz: fcd82b79aec1f5f402e1818c53d747e91e488ec3ee7b41cb35708ccf7a6a82de
3
+ metadata.gz: bb3a9002f9a8764511848a3c3d772fadf25f5f54630059aa06c9a4369335179d
4
+ data.tar.gz: a6a46c5bfdb0e7a0a93957852210185c6e9eece5faa63454c1815b5b75e6c63d
5
5
  SHA512:
6
- metadata.gz: f1b38fee7ad7e12b3d352caf206eb0bfa06d70f61b4822c87065910e4afa8aa0b449d34057115af2ad36fb49041f95ed5e4fc929078ac0f65f696e51076e6fc2
7
- data.tar.gz: 8c92d4019299e686dbeb55e880f75907ceca98eb5e285ab441e29a9984de5528f46dd0b525c61e580ed3e9605b085017a1be8aedc198800e4004fa76f3b1d133
6
+ metadata.gz: 9224cd88c0f6759480689ee6637464d0a05ff61e69093a1f834f5b1a0477543883204e81b0cce35d67b0ca66b6d00bfc2bcd2f5302e15bd4c008d21c2e3fc352
7
+ data.tar.gz: 70771f474c26f416e72a5906f06e4b8b36109daa5d492bc21a5e2a8b8cbb0ac49eb7e4c68ab36a6952dbc8d3be99db7d835390987d8ccc647304b61c8d0cebce
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef } from 'react'
1
+ import React, { useEffect, useRef, forwardRef } from 'react'
2
2
  import Body from '../pb_body/_body'
3
3
  import Icon from '../pb_icon/_icon'
4
4
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
@@ -24,7 +24,7 @@ type CheckboxProps = {
24
24
  value?: string,
25
25
  } & GlobalProps
26
26
 
27
- const Checkbox = (props: CheckboxProps): React.ReactElement => {
27
+ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
28
28
  const {
29
29
  aria = {},
30
30
  checked = false,
@@ -44,7 +44,15 @@ const Checkbox = (props: CheckboxProps): React.ReactElement => {
44
44
  value = '',
45
45
  } = props
46
46
 
47
- const checkRef = useRef(null)
47
+ const internalRef = useRef<HTMLInputElement>(null)
48
+ const setRefs = (el: HTMLInputElement) => {
49
+ internalRef.current = el
50
+ if (typeof ref === 'function') {
51
+ ref(el)
52
+ } else if (ref) {
53
+ (ref as React.MutableRefObject<HTMLInputElement | null>).current = el
54
+ }
55
+ }
48
56
  const ariaProps = buildAriaProps(aria)
49
57
  const dataProps = buildDataProps(data)
50
58
  const htmlProps = buildHtmlProps(htmlOptions)
@@ -56,9 +64,9 @@ const Checkbox = (props: CheckboxProps): React.ReactElement => {
56
64
  )
57
65
 
58
66
  useEffect(() => {
59
- if (checkRef.current) {
60
- checkRef.current.checked = checked
61
- checkRef.current.indeterminate = indeterminate
67
+ if (internalRef.current) {
68
+ internalRef.current.checked = checked
69
+ internalRef.current.indeterminate = indeterminate
62
70
  }
63
71
  }, [indeterminate, checked])
64
72
 
@@ -72,7 +80,7 @@ const Checkbox = (props: CheckboxProps): React.ReactElement => {
72
80
  disabled={disabled}
73
81
  name={name}
74
82
  onChange={onChange}
75
- ref={checkRef}
83
+ ref={setRefs}
76
84
  tabIndex={tabIndex}
77
85
  type="checkbox"
78
86
  value={value}
@@ -119,6 +127,7 @@ const Checkbox = (props: CheckboxProps): React.ReactElement => {
119
127
  </Body>
120
128
  </label>
121
129
  )
122
- }
130
+ })
123
131
 
132
+ Checkbox.displayName = "Checkbox"
124
133
  export default Checkbox
@@ -106,3 +106,19 @@ test('has disabled attribute', () => {
106
106
  const input = kit.querySelector('input')
107
107
  expect(input).toHaveAttribute('disabled')
108
108
  })
109
+
110
+ test('has ref in the input element', () => {
111
+ const ref = React.createRef()
112
+ render(
113
+ <Checkbox
114
+ data={{ testid: testId }}
115
+ name="checkbox-name"
116
+ ref={ref}
117
+ text="Checkbox"
118
+ value="check-box value"
119
+ />
120
+ )
121
+
122
+ expect(ref.current).not.toBeNull()
123
+ expect(ref.current?.tagName).toBe('INPUT')
124
+ })
@@ -0,0 +1,69 @@
1
+ import React, { useState } from "react"
2
+ import { useForm } from "react-hook-form"
3
+ import { Button, Checkbox, Flex, Body } from "playbook-ui"
4
+
5
+ const CheckboxReactHook = () => {
6
+ const { register, handleSubmit } = useForm({
7
+ defaultValues: {
8
+ Small: false,
9
+ Medium: false,
10
+ Large: false,
11
+ },
12
+ })
13
+
14
+ const [submittedData, setSubmittedData] = useState({
15
+ Small: false,
16
+ Medium: false,
17
+ Large: false,
18
+ })
19
+
20
+ const onSubmit = (data) => {
21
+ setSubmittedData(data)
22
+ }
23
+
24
+ return (
25
+ <Flex orientation="row">
26
+ <Flex align="start"
27
+ orientation="column"
28
+ paddingRight="lg"
29
+ >
30
+ <form onSubmit={handleSubmit(onSubmit)}>
31
+ <Checkbox padding="xs"
32
+ text="Small"
33
+ {...register("Small")}
34
+ />
35
+ <br />
36
+ <Checkbox padding="xs"
37
+ text="Medium"
38
+ {...register("Medium")}
39
+ />
40
+ <br />
41
+ <Checkbox padding="xs"
42
+ text="Large"
43
+ {...register("Large")}
44
+ />
45
+ <br />
46
+ <Button htmlType="submit"
47
+ marginTop="sm"
48
+ text="submit"
49
+ />
50
+ </form>
51
+ </Flex>
52
+ <Flex align="start"
53
+ orientation="column"
54
+ >
55
+ <Body padding="xs"
56
+ text={`Small: ${submittedData.Small ? "true" : "false"}`}
57
+ />
58
+ <Body padding="xs"
59
+ text={`Medium: ${submittedData.Medium ? "true" : "false"}`}
60
+ />
61
+ <Body padding="xs"
62
+ text={`Large: ${submittedData.Large ? "true" : "false"}`}
63
+ />
64
+ </Flex>
65
+ </Flex>
66
+ )
67
+ }
68
+
69
+ export default CheckboxReactHook
@@ -0,0 +1 @@
1
+ You can pass react hook props to the checkbox kit.
@@ -11,6 +11,7 @@ examples:
11
11
  react:
12
12
  - checkbox_default: Default
13
13
  - checkbox_checked: Load as checked
14
+ - checkbox_react_hook: React Hook Form
14
15
  - checkbox_custom: Custom Checkbox
15
16
  - checkbox_error: Default w/ Error
16
17
  - checkbox_indeterminate: Indeterminate Checkbox
@@ -21,4 +22,4 @@ examples:
21
22
  - checkbox_error_swift: Default w/ Error
22
23
  - checkbox_indeterminate_swift: Indeterminate Checkbox
23
24
  - checkbox_props_swift: ""
24
-
25
+
@@ -1,5 +1,6 @@
1
1
  export { default as CheckboxDefault } from './_checkbox_default.jsx'
2
2
  export { default as CheckboxCustom } from './_checkbox_custom.jsx'
3
+ export { default as CheckboxReactHook } from './_checkbox_react_hook.jsx'
3
4
  export { default as CheckboxError } from './_checkbox_error.jsx'
4
5
  export { default as CheckboxChecked } from './_checkbox_checked.jsx'
5
6
  export { default as CheckboxIndeterminate } from './_checkbox_indeterminate.jsx'
@@ -29,6 +29,7 @@ type DatePickerProps = {
29
29
  hideLabel?: boolean,
30
30
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
31
31
  id?: string,
32
+ initializeOnce?: boolean,
32
33
  inLine?: boolean,
33
34
  inputAria?: { [key: string]: string },
34
35
  inputData?: { [key: string]: string },
@@ -73,6 +74,7 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
73
74
  hideLabel = false,
74
75
  htmlOptions = {},
75
76
  id,
77
+ initializeOnce = false,
76
78
  inLine = false,
77
79
  inputAria = {},
78
80
  inputData = {},
@@ -134,7 +136,7 @@ useEffect(() => {
134
136
  yearRange,
135
137
  required: false,
136
138
  }, scrollContainer)
137
- })
139
+ }, initializeOnce ? [] : undefined)
138
140
  const filteredProps = {...props}
139
141
  if (filteredProps.marginBottom === undefined) {
140
142
  filteredProps.marginBottom = "sm"
@@ -1,3 +1,2 @@
1
1
  <%= pb_rails("icon_button") %>
2
- </br>
3
- <%= pb_rails("icon_button", props: {variant: "link"}) %>
2
+ <%= pb_rails("icon_button", props: {variant: "link", margin_top: "md" }) %>
@@ -0,0 +1,27 @@
1
+ <%= pb_rails("flex", props: { align: "center"}) do %>
2
+ <%= pb_rails("icon_button", props: {size: "lg"}) %> <span>Large</span>
3
+ <% end %>
4
+
5
+ <%= pb_rails("flex", props: { align: "center" }) do %>
6
+ <%= pb_rails("icon_button", props: {size: "sm"}) %> <span>Small</span>
7
+ <% end %>
8
+
9
+ <%= pb_rails("flex", props: { align: "center" }) do %>
10
+ <%= pb_rails("icon_button", props: {size: "xs"}) %> <span>XSmall</span>
11
+ <% end %>
12
+
13
+ <%= pb_rails("flex", props: { align: "center", margin_top: "md" }) do %>
14
+ <%= pb_rails("icon_button", props: {size: "1x"}) %> <span>1x</span>
15
+ <% end %>
16
+
17
+ <%= pb_rails("flex", props: { align: "center" }) do %>
18
+ <%= pb_rails("icon_button", props: {size: "2x"}) %> <span>2x</span>
19
+ <% end %>
20
+
21
+ <%= pb_rails("flex", props: { align: "center" }) do %>
22
+ <%= pb_rails("icon_button", props: {size: "3x"}) %> <span>3x</span>
23
+ <% end %>
24
+
25
+ <%= pb_rails("flex", props: { align: "center" }) do %>
26
+ <%= pb_rails("icon_button", props: {size: "4x"}) %> <span>4x</span>
27
+ <% end %>
@@ -2,6 +2,4 @@ examples:
2
2
 
3
3
  rails:
4
4
  - icon_button_default: Default
5
-
6
-
7
-
5
+ - icon_button_sizes: Sizes
@@ -8,7 +8,7 @@
8
8
  <%= pb_rails("icon", props: { icon: object.icon,
9
9
  fixed_width: true,
10
10
  dark: object.dark,
11
- size: "2x",
11
+ size: object.size,
12
12
  color: "text_lt_default",
13
13
  classname: "icon_button_icon",
14
14
  padding_x: "xxs", padding_y: "xs" }) %>
@@ -14,6 +14,9 @@ module Playbook
14
14
  prop :variant, type: Playbook::Props::Enum,
15
15
  values: %w[default link],
16
16
  default: "default"
17
+ prop :size, type: Playbook::Props::Enum,
18
+ values: %w[1x 2x 3x 4x 5x 6x 7x 8x 9x 10x xs sm lg],
19
+ default: "2x"
17
20
  def classname
18
21
  generate_classname("pb_icon_button_kit", variant)
19
22
  end
@@ -0,0 +1,47 @@
1
+ <%= pb_rails("table", props: { size: "sm" }) do %>
2
+ <%= pb_rails("table/table_head") do %>
3
+ <%= pb_rails("table/table_row") do %>
4
+ <%= pb_rails("table/table_header", props: { text: "Column 1" }) %>
5
+ <%= pb_rails("table/table_header", props: { text: "Column 2" }) %>
6
+ <%= pb_rails("table/table_header", props: { text: "Column 3" }) %>
7
+ <%= pb_rails("table/table_header", props: { text: "Column 4" }) %>
8
+ <%= pb_rails("table/table_header", props: { text: "Column 5" }) %>
9
+ <%= pb_rails("table/table_header", props: { text: "" }) %>
10
+ <% end %>
11
+ <% end %>
12
+ <%= pb_rails("table/table_body") do %>
13
+ <%= pb_rails("table/table_row", props: { cursor: "pointer", html_options: { onclick: "alert('Row 1 clicked')" } }) do %>
14
+ <%= pb_rails("table/table_cell", props: { text: "Value 1" }) %>
15
+ <%= pb_rails("table/table_cell", props: { text: "Value 2" }) %>
16
+ <%= pb_rails("table/table_cell", props: { text: "Value 3" }) %>
17
+ <%= pb_rails("table/table_cell", props: { text: "Value 4" }) %>
18
+ <%= pb_rails("table/table_cell", props: { text: "Value 5" }) %>
19
+ <%= pb_rails("table/table_cell", props: { text_align: "right" }) do %>
20
+ <%= pb_rails("icon", props: { color: "primary_action", fixed_width: true, icon: "chevron-right", size: "xs" }) %>
21
+ <% end %>
22
+ <% end %>
23
+
24
+ <%= pb_rails("table/table_row", props: { cursor: "pointer", html_options: { onclick: "alert('Row 2 clicked')" } }) do %>
25
+ <%= pb_rails("table/table_cell", props: { text: "Value 1" }) %>
26
+ <%= pb_rails("table/table_cell", props: { text: "Value 2" }) %>
27
+ <%= pb_rails("table/table_cell", props: { text: "Value 3" }) %>
28
+ <%= pb_rails("table/table_cell", props: { text: "Value 4" }) %>
29
+ <%= pb_rails("table/table_cell", props: { text: "Value 5" }) %>
30
+ <%= pb_rails("table/table_cell", props: { text_align: "right" }) do %>
31
+ <%= pb_rails("icon", props: { color: "primary_action", fixed_width: true, icon: "chevron-right", size: "xs" }) %>
32
+ <% end %>
33
+ <% end %>
34
+
35
+ <%= pb_rails("table/table_row", props: { cursor: "pointer", html_options: { onclick: "alert('Row 3 clicked')" } }) do %>
36
+ <%= pb_rails("table/table_cell", props: { text: "Value 1" }) %>
37
+ <%= pb_rails("table/table_cell", props: { text: "Value 2" }) %>
38
+ <%= pb_rails("table/table_cell", props: { text: "Value 3" }) %>
39
+ <%= pb_rails("table/table_cell", props: { text: "Value 4" }) %>
40
+ <%= pb_rails("table/table_cell", props: { text: "Value 5" }) %>
41
+ <%= pb_rails("table/table_cell", props: { text_align: "right" }) do %>
42
+ <%= pb_rails("icon", props: { color: "primary_action", fixed_width: true, icon: "chevron-right", size: "xs" }) %>
43
+ <% end %>
44
+ <% end %>
45
+ <% end %>
46
+ <% end %>
47
+
@@ -0,0 +1,88 @@
1
+ import React from 'react'
2
+ import { Table, Icon } from 'playbook-ui'
3
+
4
+ const TableWithClickableRows = (props) => {
5
+
6
+
7
+ return (
8
+ <Table
9
+ size="sm"
10
+ {...props}
11
+ >
12
+ <Table.Head>
13
+ <Table.Row>
14
+ <Table.Header>{"Column 1"}</Table.Header>
15
+ <Table.Header>{"Column 2"}</Table.Header>
16
+ <Table.Header>{"Column 3"}</Table.Header>
17
+ <Table.Header>{"Column 4"}</Table.Header>
18
+ <Table.Header>{"Column 5"}</Table.Header>
19
+ <Table.Header>{""}</Table.Header>
20
+ </Table.Row>
21
+ </Table.Head>
22
+ <Table.Body>
23
+ <Table.Row
24
+ cursor="pointer"
25
+ htmlOptions={{ onClick: () => alert("Row 1 clicked") }}
26
+ {...props}
27
+ >
28
+ <Table.Cell>{"Value 1"}</Table.Cell>
29
+ <Table.Cell>{"Value 2"}</Table.Cell>
30
+ <Table.Cell>{"Value 3"}</Table.Cell>
31
+ <Table.Cell>{"Value 4"}</Table.Cell>
32
+ <Table.Cell>{"Value 5"}</Table.Cell>
33
+ <Table.Cell textAlign="right">
34
+ <Icon
35
+ color="primary_action"
36
+ fixedWidth
37
+ icon="chevron-right"
38
+ size="xs"
39
+ {...props}
40
+ />
41
+ </Table.Cell>
42
+ </Table.Row>
43
+ <Table.Row
44
+ cursor="pointer"
45
+ htmlOptions={{ onClick: () => alert("Row 2 clicked") }}
46
+ {...props}
47
+ >
48
+ <Table.Cell>{"Value 1"}</Table.Cell>
49
+ <Table.Cell>{"Value 2"}</Table.Cell>
50
+ <Table.Cell>{"Value 3"}</Table.Cell>
51
+ <Table.Cell>{"Value 4"}</Table.Cell>
52
+ <Table.Cell>{"Value 5"}</Table.Cell>
53
+ <Table.Cell textAlign="right">
54
+ <Icon
55
+ color="primary_action"
56
+ fixedWidth
57
+ icon="chevron-right"
58
+ size="xs"
59
+ {...props}
60
+ />
61
+ </Table.Cell>
62
+ </Table.Row>
63
+ <Table.Row
64
+ cursor="pointer"
65
+ htmlOptions={{ onClick: () => alert("Row 3 clicked") }}
66
+ {...props}
67
+ >
68
+ <Table.Cell>{"Value 1"}</Table.Cell>
69
+ <Table.Cell>{"Value 2"}</Table.Cell>
70
+ <Table.Cell>{"Value 3"}</Table.Cell>
71
+ <Table.Cell>{"Value 4"}</Table.Cell>
72
+ <Table.Cell>{"Value 5"}</Table.Cell>
73
+ <Table.Cell textAlign="right">
74
+ <Icon
75
+ color="primary_action"
76
+ fixedWidth
77
+ icon="chevron-right"
78
+ size="xs"
79
+ {...props}
80
+ />
81
+ </Table.Cell>
82
+ </Table.Row>
83
+ </Table.Body>
84
+ </Table>
85
+ )
86
+ }
87
+
88
+ export default TableWithClickableRows
@@ -0,0 +1 @@
1
+ Clickable table rows do not require any additional props. This doc example showcases how to set them up using `html_options`/`htmlOptions` and click events. Using the global prop for cursor to set it to "pointer" is also recommended for better UX.
@@ -0,0 +1,96 @@
1
+ <% checkboxes = [
2
+ { name: 'Coffee', id: 'coffee', checked: false },
3
+ { name: 'Ice Cream', id: 'ice-cream', checked: false },
4
+ { name: 'Chocolate', id: 'chocolate', checked: true }
5
+ ] %>
6
+
7
+ <%= pb_rails("flex", props: { justify: "end", margin_bottom: "sm" }) do %>
8
+ <%= pb_rails("flex", props: { justify: "end", margin_bottom: "sm" }) do %>
9
+ <%= pb_rails("button", props: { text: "Delete", id: "delete-button" }) %>
10
+ <% end %>
11
+ <% end %>
12
+
13
+ <%= pb_rails("table", props: { size: "sm" }) do %>
14
+ <%= pb_rails("table/table_head") do %>
15
+ <%= pb_rails("table/table_row") do %>
16
+ <%= pb_rails("table/table_header") do %>
17
+ <%= pb_rails("checkbox", props: {
18
+ checked: true,
19
+ value: "checkbox-value",
20
+ name: "main-checkbox-selectable",
21
+ indeterminate: true,
22
+ id: "checkbox-selectable"
23
+ }) %>
24
+ <% end %>
25
+ <%= pb_rails("table/table_header", props: { text: "Column 1" }) %>
26
+ <%= pb_rails("table/table_header", props: { text: "Column 2" }) %>
27
+ <%= pb_rails("table/table_header", props: { text: "Column 3" }) %>
28
+ <%= pb_rails("table/table_header", props: { text: "Column 4" }) %>
29
+ <%= pb_rails("table/table_header", props: { text: "Column 5" }) %>
30
+ <% end %>
31
+ <% end %>
32
+ <%= pb_rails("table/table_body") do %>
33
+ <% checkboxes.each_with_index do |checkbox, index| %>
34
+ <%= pb_rails("table/table_row") do %>
35
+ <%= pb_rails("table/table_cell") do %>
36
+ <%= pb_rails("checkbox", props: { checked: checkbox[:checked], id: "#{checkbox[:id]}-selectable-checkbox", name: "#{checkbox[:id]}-selectable-checkbox", on_change: "updateCheckboxes(#{index})", value: "check-box value" }) %>
37
+ <% end %>
38
+ <%= pb_rails("table/table_cell") do %>
39
+ <%= pb_rails("image", props: { alt: "picture of a misty forest", size: "xs", url: "https://unsplash.it/500/400/?image=634" }) %>
40
+ <% end %>
41
+ <%= pb_rails("table/table_cell", props: { text: "Value 2" }) %>
42
+ <%= pb_rails("table/table_cell", props: { text: "Value 3" }) %>
43
+ <%= pb_rails("table/table_cell", props: { text: "Value 4" }) %>
44
+ <%= pb_rails("table/table_cell", props: { text: "Value 5" }) %>
45
+ <% end %>
46
+ <% end %>
47
+ <% end %>
48
+ <% end %>
49
+
50
+ <script>
51
+ document.addEventListener('DOMContentLoaded', function() {
52
+ const mainCheckboxWrapper = document.getElementById('checkbox-selectable');
53
+ const mainCheckbox = document.getElementsByName("main-checkbox-selectable")[0];
54
+ const childCheckboxes = document.querySelectorAll('input[type="checkbox"][id$="selectable-checkbox"]');
55
+ const deleteButton = document.getElementById('delete-button');
56
+
57
+ const updateDeleteButton = () => {
58
+ const anyChecked = Array.from(childCheckboxes).some(checkbox => checkbox.checked);
59
+ deleteButton.style.display = anyChecked ? 'block' : 'none';
60
+ };
61
+
62
+ const updateMainCheckbox = () => {
63
+ // Count the number of checked child checkboxes
64
+ const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
65
+ // Determine if the main checkbox should be in an indeterminate state
66
+ const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
67
+
68
+ // Set the main checkbox states
69
+ mainCheckbox.indeterminate = indeterminate;
70
+ mainCheckbox.checked = checkedCount > 0;
71
+
72
+ // Determine the icon class to add and remove based on the number of checked checkboxes
73
+ const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
74
+ const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
75
+
76
+ // Add and remove the icon class to the main checkbox wrapper
77
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
78
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
79
+
80
+ // Toggle the visibility of the checkbox icon based on the indeterminate state
81
+ mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
82
+ mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
83
+
84
+ updateDeleteButton();
85
+ };
86
+
87
+ mainCheckbox.addEventListener('change', function() {
88
+ childCheckboxes.forEach(cb => cb.checked = this.checked);
89
+ updateMainCheckbox();
90
+ });
91
+
92
+ childCheckboxes.forEach(cb => {
93
+ cb.addEventListener('change', updateMainCheckbox);
94
+ });
95
+ });
96
+ </script>
@@ -0,0 +1,101 @@
1
+ import React, { useState } from 'react'
2
+ import { Table, Checkbox, Image, Flex, Button } from 'playbook-ui'
3
+
4
+ const TableWithSelectableRows = (props) => {
5
+ const [checkboxes, setCheckboxes] = useState([
6
+ { name: "Coffee", checked: false },
7
+ { name: "Ice Cream", checked: false },
8
+ { name: "Chocolate", checked: true },
9
+ ]);
10
+
11
+ const isAllChecked = !checkboxes.find((checkbox) => !checkbox.checked);
12
+ const isNoneChecked = !checkboxes.find((checkbox) => checkbox.checked);
13
+
14
+ const processCheckboxes = (checked) =>
15
+ checkboxes.slice(0).map((checkbox) => {
16
+ checkbox.checked = checked;
17
+ return checkbox;
18
+ });
19
+
20
+ const onToggleAll = () => {
21
+ setCheckboxes(
22
+ isNoneChecked ? processCheckboxes(true) : processCheckboxes(false)
23
+ );
24
+ };
25
+
26
+ const updateCheckboxes = (checkbox, index) => {
27
+ const newCheckboxes = checkboxes.slice(0);
28
+ newCheckboxes[index].checked = !checkbox.checked;
29
+ setCheckboxes(newCheckboxes);
30
+ };
31
+
32
+ return (
33
+ <>
34
+ <Flex
35
+ justify="end"
36
+ marginBottom="sm"
37
+ >
38
+ {!isNoneChecked && (
39
+ <Flex
40
+ justify="end"
41
+ marginBottom="sm"
42
+ >
43
+ <Button>Delete</Button>
44
+ </Flex>
45
+ )}
46
+ </Flex>
47
+ <Table
48
+ size="sm"
49
+ {...props}
50
+ >
51
+ <Table.Head>
52
+ <Table.Row>
53
+ <Table.Header>
54
+ <Checkbox
55
+ checked={isAllChecked}
56
+ indeterminate={!isAllChecked && !isNoneChecked}
57
+ name="checkbox-name"
58
+ onChange={onToggleAll}
59
+ value="check-box value"
60
+ />
61
+ </Table.Header>
62
+ <Table.Header>{"Column 1"}</Table.Header>
63
+ <Table.Header>{"Column 2"}</Table.Header>
64
+ <Table.Header>{"Column 3"}</Table.Header>
65
+ <Table.Header>{"Column 4"}</Table.Header>
66
+ <Table.Header>{"Column 5"}</Table.Header>
67
+ </Table.Row>
68
+ </Table.Head>
69
+ <Table.Body>
70
+ {checkboxes.map((checkbox, index) => (
71
+ <Table.Row key={index}>
72
+ <Table.Cell>
73
+ <Checkbox
74
+ checked={checkbox.checked}
75
+ name={checkbox.name}
76
+ onChange={() => {
77
+ updateCheckboxes(checkbox, index);
78
+ }}
79
+ value="check-box value"
80
+ />
81
+ </Table.Cell>
82
+ <Table.Cell>
83
+ <Image
84
+ alt="picture of a misty forest"
85
+ size="xs"
86
+ url="https://unsplash.it/500/400/?image=634"
87
+ />
88
+ </Table.Cell>
89
+ <Table.Cell>{"Value 2"}</Table.Cell>
90
+ <Table.Cell>{"Value 3"}</Table.Cell>
91
+ <Table.Cell>{"Value 4"}</Table.Cell>
92
+ <Table.Cell>{"Value 5"}</Table.Cell>
93
+ </Table.Row>
94
+ ))}
95
+ </Table.Body>
96
+ </Table>
97
+ </>
98
+ )
99
+ }
100
+
101
+ export default TableWithSelectableRows
@@ -0,0 +1 @@
1
+ Use the Checkbox kit with the Table to achieve the selectable row functionality seen here.
@@ -34,6 +34,8 @@ examples:
34
34
  - table_with_collapsible_with_custom_content_rails: Table with Collapsible with Custom Content
35
35
  - table_with_collapsible_with_nested_rows_rails: Table with Collapsible with Nested Rows
36
36
  - table_with_collapsible_with_nested_table_rails: Table with Collapsible with Nested Table
37
+ - table_with_clickable_rows: Table with Clickable Rows
38
+ - table_with_selectable_rows: Table with Selectable Rows
37
39
 
38
40
  react:
39
41
  - table_sm: Small
@@ -70,3 +72,5 @@ examples:
70
72
  - table_with_collapsible_with_custom_content: Table with Collapsible with Custom Content
71
73
  - table_with_collapsible_with_nested_rows: Table with Collapsible with Nested Rows
72
74
  - table_with_collapsible_with_nested_table: Table with Collapsible with Nested Table
75
+ - table_with_clickable_rows: Table with Clickable Rows
76
+ - table_with_selectable_rows: Table with Selectable Rows
@@ -32,4 +32,6 @@ export { default as TableWithCollapsible } from './_table_with_collapsible.jsx'
32
32
  export { default as TableWithCollapsibleWithCustomContent } from './_table_with_collapsible_with_custom_content.jsx'
33
33
  export { default as TableWithCollapsibleWithNestedTable } from './_table_with_collapsible_with_nested_table.jsx'
34
34
  export { default as TableWithCollapsibleWithNestedRows } from './_table_with_collapsible_with_nested_rows.jsx'
35
- export { default as TableWithCollapsibleWithCustomClick } from './_table_with_collapsible_with_custom_click.jsx'
35
+ export { default as TableWithCollapsibleWithCustomClick } from './_table_with_collapsible_with_custom_click.jsx'
36
+ export { default as TableWithSelectableRows } from './_table_with_selectable_rows.jsx'
37
+ export { default as TableWithClickableRows } from './_table_with_clickable_rows.jsx'