playbook_ui 14.15.0.pre.alpha.play1949lodashremoval3of36746 → 14.15.0.pre.alpha.play1949lodashremoval3of36815

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_default.jsx +1 -0
  3. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.html.erb +3 -0
  4. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -0
  5. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.scss +2 -2
  6. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +67 -0
  7. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +67 -0
  8. data/app/pb_kits/playbook/pb_icon/_icon.scss +8 -1
  9. data/app/pb_kits/playbook/pb_icon/docs/_icon_color.html.erb +10 -4
  10. data/app/pb_kits/playbook/pb_icon/docs/_icon_color.jsx +49 -24
  11. data/app/pb_kits/playbook/pb_icon_button/_icon_button.tsx +4 -1
  12. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_click.jsx +13 -0
  13. data/app/pb_kits/playbook/pb_icon_button/docs/example.yml +1 -0
  14. data/app/pb_kits/playbook/pb_icon_button/docs/index.js +1 -0
  15. data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +5 -1
  16. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +23 -0
  17. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +42 -6
  18. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +1 -1
  19. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.html.erb +76 -0
  20. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.jsx +94 -0
  21. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.md +1 -0
  22. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.html.erb +75 -0
  23. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.jsx +93 -0
  24. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.md +3 -0
  25. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.html.erb +75 -0
  26. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.jsx +93 -0
  27. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.md +3 -0
  28. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.html.erb +74 -0
  29. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.jsx +92 -0
  30. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.md +3 -0
  31. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.html.erb +72 -0
  32. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.jsx +97 -0
  33. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +71 -0
  34. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +91 -0
  35. data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +14 -2
  36. data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +6 -0
  37. data/app/pb_kits/playbook/pb_multi_level_select/index.js +105 -0
  38. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +10 -0
  39. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select_options.tsx +1 -0
  40. data/app/pb_kits/playbook/pb_nav/_nav.scss +5 -0
  41. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +4 -0
  42. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +3 -0
  43. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_disabled.html.erb +19 -0
  44. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_disabled.jsx +23 -0
  45. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
  46. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  47. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +3 -0
  48. data/app/pb_kits/playbook/pb_user/_user.tsx +78 -13
  49. data/app/pb_kits/playbook/pb_user/docs/_user_font_options.html.erb +22 -0
  50. data/app/pb_kits/playbook/pb_user/docs/_user_font_options.jsx +40 -0
  51. data/app/pb_kits/playbook/pb_user/docs/_user_font_options_rails.md +5 -0
  52. data/app/pb_kits/playbook/pb_user/docs/_user_font_options_react.md +5 -0
  53. data/app/pb_kits/playbook/pb_user/docs/example.yml +2 -0
  54. data/app/pb_kits/playbook/pb_user/docs/index.js +1 -0
  55. data/app/pb_kits/playbook/pb_user/user.html.erb +27 -6
  56. data/app/pb_kits/playbook/pb_user/user.rb +17 -1
  57. data/app/pb_kits/playbook/pb_user/user.test.js +182 -1
  58. data/app/pb_kits/playbook/tokens/_colors.scss +1 -4
  59. data/app/pb_kits/playbook/utilities/object.test.js +149 -1
  60. data/app/pb_kits/playbook/utilities/object.ts +16 -76
  61. data/dist/chunks/{_typeahead-C_orSAyx.js → _typeahead-DZNrDsCe.js} +3 -3
  62. data/dist/chunks/_weekday_stacked-BwM21XCO.js +45 -0
  63. data/dist/chunks/{lib-ChtLutkU.js → lib-DpO_YjaF.js} +1 -1
  64. data/dist/chunks/{pb_form_validation-CoiIaTHi.js → pb_form_validation-C3rQtNR-.js} +1 -1
  65. data/dist/chunks/vendor.js +1 -1
  66. data/dist/playbook-doc.js +1 -1
  67. data/dist/playbook-rails-react-bindings.js +1 -1
  68. data/dist/playbook-rails.js +1 -1
  69. data/dist/playbook.css +1 -1
  70. data/lib/playbook/forms/builder/multi_level_select_field.rb +2 -0
  71. data/lib/playbook/version.rb +1 -1
  72. metadata +30 -6
  73. data/dist/chunks/_weekday_stacked-D7pAcXO0.js +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 363360c157a79330efc2c8b4e60e45437e7fb282790e4a302da644da029d67f0
4
- data.tar.gz: e798b4832175f45fac621bbe16ac3c84d88ce499d55b7af35062125b95d4eadf
3
+ metadata.gz: 00c74c07957b56cf1da4de814303ddc2a8ddd7632aac68fff9e7d4cdd3cbf203
4
+ data.tar.gz: f27e1e2692df72b86d23da070e3ca4e78c98ec266d451f2ef31267946da5c524
5
5
  SHA512:
6
- metadata.gz: 07ffd2c95fed2422c3a4a4659a5bfdfcc51c63875d00ab3b8efa6ee29a240b92c9003c816bd0254c3350207528542e978ec6cc78b898c58a271def99c4806c8c
7
- data.tar.gz: 5118481860bb78e617854ff8916c106ba455aff24bd8bf2dcdea257cde2a40bea09c797113c67a1073a87ddbbaa8dd2d074ec8a68fa946da121ba7295a2f3ea8
6
+ metadata.gz: 97b42f8f769cd29673a57688f2f0fff0ae8894242137f0966b267f33098b0b7b6d934f4ae59302d0c3bb502f05b21e52a95fbb49072ad0a763eb5a6b571ca21e
7
+ data.tar.gz: 00fa01e72545d9ce4edadee984709233526e7279fce642627d9e89dfff0de4b3488013685ed0744ece60475eee2250160a9b44eead8f65169227d7d7b21c9709
@@ -1,6 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
 
3
3
  import Flex from '../../pb_flex/_flex'
4
+ import Image from '../../pb_image/_image'
4
5
  import Draggable from '../../pb_draggable/_draggable'
5
6
  import { DraggableProvider } from '../../pb_draggable/context'
6
7
 
@@ -0,0 +1,3 @@
1
+
2
+ <%= pb_rails("body", props: { text: " The breakpoint prop determines when the Drawer is always visible. Above the specified breakpoint, the Drawer remains open on the page. Below it, only the trigger element is shown, allowing you to toggle the drawer open and closed. To see this in action, click the button below and resize your window.", padding_bottom: "md" }) %>
3
+ <%= pb_rails("button", props: { text: "Open Doc Example in New Tab", new_window: true, link: "/drawer_page", margin_right: "lg" }) %>
@@ -6,6 +6,7 @@ examples:
6
6
  - drawer_menu: Within Element
7
7
  - drawer_sizes: Sizes
8
8
  - drawer_overlay: Overlay
9
+ - drawer_breakpoints: Breakpoints
9
10
  - drawer_borders: Borders
10
11
 
11
12
 
@@ -7,7 +7,7 @@ $pb_pill_height: 25px;
7
7
 
8
8
 
9
9
  $confirmation_toast_colors: (
10
- neutral: $neutral,
10
+ neutral: $text_lt_light,
11
11
  success: $success,
12
12
  error: $error,
13
13
  tip: transparent,
@@ -87,7 +87,7 @@ $confirmation_toast_colors: (
87
87
  overflow: hidden;
88
88
  display: -webkit-box;
89
89
  -webkit-line-clamp: 3;
90
- -webkit-box-orient: vertical;
90
+ -webkit-box-orient: vertical;
91
91
  white-space: normal;
92
92
  text-align: left;
93
93
  }
@@ -22,6 +22,72 @@
22
22
 
23
23
  %>
24
24
 
25
+ <% treeData = [{
26
+ label: "Power Home Remodeling",
27
+ value: "Power Home Remodeling",
28
+ id: "100",
29
+ expanded: true,
30
+ children: [
31
+ {
32
+ label: "People",
33
+ value: "People",
34
+ id: "101",
35
+ expanded: true,
36
+ children: [
37
+ {
38
+ label: "Talent Acquisition",
39
+ value: "Talent Acquisition",
40
+ id: "102",
41
+ },
42
+ {
43
+ label: "Business Affairs",
44
+ value: "Business Affairs",
45
+ id: "103",
46
+ children: [
47
+ {
48
+ label: "Initiatives",
49
+ value: "Initiatives",
50
+ id: "104",
51
+ },
52
+ {
53
+ label: "Learning & Development",
54
+ value: "Learning & Development",
55
+ id: "105",
56
+ },
57
+ ],
58
+ },
59
+ {
60
+ label: "People Experience",
61
+ value: "People Experience",
62
+ id: "106",
63
+ },
64
+ ],
65
+ },
66
+ {
67
+ label: "Contact Center",
68
+ value: "Contact Center",
69
+ id: "107",
70
+ children: [
71
+ {
72
+ label: "Appointment Management",
73
+ value: "Appointment Management",
74
+ id: "108",
75
+ },
76
+ {
77
+ label: "Customer Service",
78
+ value: "Customer Service",
79
+ id: "109",
80
+ },
81
+ {
82
+ label: "Energy",
83
+ value: "Energy",
84
+ id: "110",
85
+ },
86
+ ],
87
+ },
88
+ ],
89
+ }] %>
90
+
25
91
  <%= pb_form_with(scope: :example, url: "", method: :get) do |form| %>
26
92
  <%= form.typeahead :example_typeahead, props: { data: { typeahead_example1: true, user: {} }, label: true, placeholder: "Search for a user" } %>
27
93
  <%= form.text_field :example_text_field, props: { label: true } %>
@@ -47,6 +113,7 @@
47
113
  <%= form.date_picker :example_date_picker_1, props: { label: true } %>
48
114
  <%= form.star_rating_field :example_star_rating, props: { variant: "interactive", label: true } %>
49
115
  <%= form.time_zone_select_field :example_time_zone_select, ActiveSupport::TimeZone.us_zones, { default: "Eastern Time (US & Canada)" }, props: { label: true } %>
116
+ <%= form.multi_level_select :example_multi_level_select, props: { id: "multi-level-select-form-default", tree_data: treeData, margin_bottom: "sm", label: "Example Multi Level Select field" } %>
50
117
 
51
118
  <%= form.actions do |action| %>
52
119
  <%= action.submit %>
@@ -21,6 +21,72 @@
21
21
  ]
22
22
  %>
23
23
 
24
+ <% treeData = [{
25
+ label: "Power Home Remodeling",
26
+ value: "Power Home Remodeling",
27
+ id: "100",
28
+ expanded: true,
29
+ children: [
30
+ {
31
+ label: "People",
32
+ value: "People",
33
+ id: "101",
34
+ expanded: true,
35
+ children: [
36
+ {
37
+ label: "Talent Acquisition",
38
+ value: "Talent Acquisition",
39
+ id: "102",
40
+ },
41
+ {
42
+ label: "Business Affairs",
43
+ value: "Business Affairs",
44
+ id: "103",
45
+ children: [
46
+ {
47
+ label: "Initiatives",
48
+ value: "Initiatives",
49
+ id: "104",
50
+ },
51
+ {
52
+ label: "Learning & Development",
53
+ value: "Learning & Development",
54
+ id: "105",
55
+ },
56
+ ],
57
+ },
58
+ {
59
+ label: "People Experience",
60
+ value: "People Experience",
61
+ id: "106",
62
+ },
63
+ ],
64
+ },
65
+ {
66
+ label: "Contact Center",
67
+ value: "Contact Center",
68
+ id: "107",
69
+ children: [
70
+ {
71
+ label: "Appointment Management",
72
+ value: "Appointment Management",
73
+ id: "108",
74
+ },
75
+ {
76
+ label: "Customer Service",
77
+ value: "Customer Service",
78
+ id: "109",
79
+ },
80
+ {
81
+ label: "Energy",
82
+ value: "Energy",
83
+ id: "110",
84
+ },
85
+ ],
86
+ },
87
+ ],
88
+ }] %>
89
+
24
90
  <%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
25
91
  <%= form.typeahead :example_typeahead_validation, props: { data: { typeahead_example2: true, user: {} }, label: true, placeholder: "Search for a user", required: true, validation: { message: "Please select a user." } } %>
26
92
  <%= form.text_field :example_text_field_validation, props: { label: true, required: true } %>
@@ -38,6 +104,7 @@
38
104
  <%= form.date_picker :example_date_picker_2, props: { label: true, required: true, validation_message: "Please, select a date.", allow_input: true } %>
39
105
  <%= form.star_rating_field :example_star_rating_validation, props: { variant: "interactive", label: true, required: true } %>
40
106
  <%= form.time_zone_select_field :example_time_zone_select, ActiveSupport::TimeZone.us_zones, { default: "Eastern Time (US & Canada)" }, props: { label: true, blank_selection: "Select a Time Zone...", required: true } %>
107
+ <%= form.multi_level_select :example_multi_level_select, props: { id: "multi-level-select-form", tree_data: treeData, margin_bottom: "sm", required: true, label: "Example Multi Level Select field" } %>
41
108
 
42
109
  <%= form.actions do |action| %>
43
110
  <%= action.submit %>
@@ -1,10 +1,17 @@
1
1
  @import "../tokens/colors";
2
2
 
3
+ $additional_colors: (
4
+ "light": $text_lt_light,
5
+ "lighter": $text_lt_lighter,
6
+ "link": $primary
7
+ );
8
+
3
9
  // All the merges below create $icon_colors, a map of all color tokens in colors.scss
4
10
  $merge_kits1: map-merge($status_colors, $category_colors);
5
11
  $merge_kits2: map-merge($merge_kits1, $product_colors);
6
12
  $merge_kits3: map-merge($merge_kits2, $text_colors);
7
- $icon_colors: map-merge($merge_kits3, $data_colors);
13
+ $merge_kits4: map-merge($merge_kits3, $data_colors);
14
+ $icon_colors: map-merge($merge_kits4, $additional_colors);
8
15
 
9
16
  .pb_custom_icon, .pb_icon_kit {
10
17
  @each $color_name, $color_value in $icon_colors {
@@ -1,5 +1,11 @@
1
- <%= pb_rails("flex", props: {orientation: "column"}) do %>
2
- <%= pb_rails("icon", props: { icon: "user", fixed_width: true, color: "primary", padding_bottom: "sm", size: "2x" }) %>
3
- <%= pb_rails("icon", props: { icon: "recycle", fixed_width: true, color: "data_4", padding_bottom: "sm", size: "2x" }) %>
1
+ <%= pb_rails("flex", props: { margin_bottom: "sm" }) do %>
2
+ <%= pb_rails("icon", props: { icon: "user", fixed_width: true, color: "primary", size: "2x" }) %>
3
+ <%= pb_rails("icon", props: { icon: "recycle", fixed_width: true, color: "data_4", size: "2x" }) %>
4
4
  <%= pb_rails("icon", props: { icon: "roofing", fixed_width: true, color: "product_5_background", size: "2x" }) %>
5
- <% end %>
5
+ <% end %>
6
+
7
+ <%= pb_rails("flex", props: {}) do %>
8
+ <%= pb_rails("icon", props: { icon: "user", fixed_width: true, color: "light", size: "2x" }) %>
9
+ <%= pb_rails("icon", props: { icon: "recycle", fixed_width: true, color: "lighter", size: "2x" }) %>
10
+ <%= pb_rails("icon", props: { icon: "roofing", fixed_width: true, color: "link", size: "2x" }) %>
11
+ <% end %>
@@ -1,32 +1,57 @@
1
1
  import React from "react"
2
2
  import Icon from "../_icon"
3
+ import Flex from "../../pb_flex/_flex"
3
4
 
4
5
  const IconDefault = (props) => {
5
6
  return (
6
- <div style={{ display: "flex", flexDirection: "column"}}>
7
- <Icon
8
- color="primary"
9
- fixedWidth
10
- icon="user"
11
- paddingBottom="sm"
12
- size="2x"
13
- {...props}
14
- />
15
- <Icon
16
- color="data_4"
17
- fixedWidth
18
- icon="recycle"
19
- paddingBottom="sm"
20
- size="2x"
21
- {...props}
22
- />
23
- <Icon
24
- color="product_5_background"
25
- fixedWidth
26
- icon="product-roofing"
27
- size="2x"
28
- {...props}
29
- />
7
+ <div>
8
+ <Flex marginBottom="sm">
9
+ <Icon
10
+ color="primary"
11
+ fixedWidth
12
+ icon="user"
13
+ size="2x"
14
+ {...props}
15
+ />
16
+ <Icon
17
+ color="data_4"
18
+ fixedWidth
19
+ icon="recycle"
20
+ size="2x"
21
+ {...props}
22
+ />
23
+ <Icon
24
+ color="product_5_background"
25
+ fixedWidth
26
+ icon="product-roofing"
27
+ size="2x"
28
+ {...props}
29
+ />
30
+ </Flex>
31
+
32
+ <Flex>
33
+ <Icon
34
+ color="light"
35
+ fixedWidth
36
+ icon="user"
37
+ size="2x"
38
+ {...props}
39
+ />
40
+ <Icon
41
+ color="lighter"
42
+ fixedWidth
43
+ icon="recycle"
44
+ size="2x"
45
+ {...props}
46
+ />
47
+ <Icon
48
+ color="link"
49
+ fixedWidth
50
+ icon="product-roofing"
51
+ size="2x"
52
+ {...props}
53
+ />
54
+ </Flex>
30
55
  </div>
31
56
  )
32
57
  }
@@ -1,7 +1,7 @@
1
1
 
2
2
  import React from 'react'
3
3
  import classnames from 'classnames'
4
- import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
4
+ import { buildAriaProps, buildCss, buildDataProps, noop } from '../utilities/props'
5
5
  import { globalProps } from '../utilities/globalProps'
6
6
 
7
7
  import Button from '../pb_button/_button'
@@ -17,6 +17,7 @@ type IconButtonProps = {
17
17
  id?: string,
18
18
  link?: string,
19
19
  newWindow?: boolean,
20
+ onClick?: React.MouseEventHandler<HTMLElement>,
20
21
  size?: IconSizes,
21
22
  target?: string,
22
23
  variant?: 'default' | 'link',
@@ -32,6 +33,7 @@ const IconButton = (props: IconButtonProps) => {
32
33
  id,
33
34
  link,
34
35
  newWindow = false,
36
+ onClick = noop,
35
37
  size = "2x",
36
38
  target,
37
39
  variant = "default",
@@ -53,6 +55,7 @@ const IconButton = (props: IconButtonProps) => {
53
55
  htmlType={htmlType}
54
56
  link={link}
55
57
  newWindow={newWindow}
58
+ onClick={onClick}
56
59
  target={target}
57
60
  >
58
61
  <Icon
@@ -0,0 +1,13 @@
1
+ import React from 'react'
2
+ import IconButton from '../../pb_icon_button/_icon_button'
3
+
4
+ const IconButtonClick = (props) => (
5
+ <div>
6
+ <IconButton
7
+ {...props}
8
+ onClick={() => alert('Click!')}
9
+ />
10
+ </div>
11
+ )
12
+
13
+ export default IconButtonClick
@@ -7,3 +7,4 @@ examples:
7
7
  react:
8
8
  - icon_button_default: Default
9
9
  - icon_button_sizes: Sizes
10
+ - icon_button_click: Click Handler
@@ -1,2 +1,3 @@
1
1
  export { default as IconButtonDefault } from './_icon_button_default.jsx'
2
2
  export { default as IconButtonSizes } from './_icon_button_sizes.jsx'
3
+ export { default as IconButtonClick } from './_icon_button_click.jsx'
@@ -88,7 +88,11 @@ export const getDefaultCheckedItems = (
88
88
  items.forEach((item: { [key: string]: any }) => {
89
89
  if (item.checked) {
90
90
  if (item.children && item.children.length > 0) {
91
- const uncheckedChildren = item.children.filter(
91
+ // Filter out disabled children (only consider selectable items)
92
+ const selectableChildren = item.children.filter(
93
+ (child: { [key: string]: any }) => !child.disabled
94
+ );
95
+ const uncheckedChildren = selectableChildren.filter(
92
96
  (child: { [key: string]: any }) => !child.checked
93
97
  );
94
98
  if (uncheckedChildren.length === 0) {
@@ -10,6 +10,16 @@
10
10
  .pb_multi_level_select {
11
11
  font-family: $font-family-base;
12
12
 
13
+ &.error {
14
+ .wrapper {
15
+ .input_wrapper {
16
+ border-color: $error;
17
+ }
18
+ }
19
+ [class*=pb_body_kit_negative] {
20
+ margin-top: $space_xxs;
21
+ }
22
+ }
13
23
  .wrapper {
14
24
  position: relative;
15
25
 
@@ -92,4 +102,17 @@
92
102
  .open {
93
103
  display: block;
94
104
  }
105
+
106
+ &.dark {
107
+ &.error {
108
+ .wrapper {
109
+ .input_wrapper {
110
+ border-color: $error_dark;
111
+ }
112
+ }
113
+ [class*=pb_body_kit_negative] {
114
+ color: $error_dark;
115
+ }
116
+ }
117
+ }
95
118
  }
@@ -7,9 +7,12 @@ import {
7
7
  buildDataProps,
8
8
  buildHtmlProps,
9
9
  } from "../utilities/props";
10
+ import { cloneDeep } from "../utilities/object";
11
+
10
12
  import Icon from "../pb_icon/_icon";
11
13
  import FormPill from "../pb_form_pill/_form_pill";
12
- import { cloneDeep } from "../utilities/object";
14
+ import Body from "../pb_body/_body";
15
+ import Caption from "../pb_caption/_caption";
13
16
  import MultiLevelSelectOptions from "./multi_level_select_options";
14
17
  import MultiLevelSelectContext from "./context";
15
18
 
@@ -35,11 +38,14 @@ type MultiLevelSelectProps = {
35
38
  className?: string
36
39
  data?: { [key: string]: string }
37
40
  disabled?: boolean
41
+ error?: string
38
42
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
39
43
  id?: string
40
44
  inputDisplay?: "pills" | "none"
41
45
  inputName?: string
46
+ label?: string
42
47
  name?: string
48
+ required?: boolean
43
49
  returnAllSelected?: boolean
44
50
  treeData?: { [key: string]: string; }[] | any
45
51
  onChange?: (event: { target: { name?: string; value: any } }) => void
@@ -56,11 +62,14 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
56
62
  className,
57
63
  data = {},
58
64
  disabled = false,
65
+ error,
59
66
  htmlOptions = {},
60
67
  id,
61
68
  inputDisplay = "pills",
62
69
  inputName,
63
70
  name,
71
+ label,
72
+ required = false,
64
73
  returnAllSelected = false,
65
74
  treeData,
66
75
  onChange = () => null,
@@ -77,6 +86,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
77
86
  const htmlProps = buildHtmlProps(htmlOptions);
78
87
  const classes = classnames(
79
88
  buildCss("pb_multi_level_select"),
89
+ error && "error",
80
90
  globalProps(props),
81
91
  className
82
92
  );
@@ -113,7 +123,9 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
113
123
  return;
114
124
  }
115
125
  return tree.map((item: { [key: string]: any }) => {
116
- item.checked = check;
126
+ if (!item.disabled) {
127
+ item.checked = check;
128
+ }
117
129
  item.children = modifyRecursive(item.children, check);
118
130
  return item;
119
131
  });
@@ -124,12 +136,16 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
124
136
  treeData: { [key: string]: any }[],
125
137
  selectedIds: string[],
126
138
  parent_id: string | null = null,
127
- depth = 0
139
+ depth = 0,
140
+ parentDisabled = false
128
141
  ) => {
129
142
  if (!Array.isArray(treeData)) {
130
143
  return;
131
144
  }
132
145
  return treeData.map((item: { [key: string]: any } | any) => {
146
+ // An item is disabled if it is explicitly set as disabled or if its parent is disabled
147
+ const isDisabled = item.disabled || (parentDisabled && !returnAllSelected);
148
+
133
149
  const newItem = {
134
150
  ...item,
135
151
  checked: Boolean(
@@ -137,6 +153,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
137
153
  ),
138
154
  parent_id,
139
155
  depth,
156
+ disabled: isDisabled,
140
157
  };
141
158
  if (newItem.children && newItem.children.length > 0) {
142
159
  const children =
@@ -147,7 +164,8 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
147
164
  children,
148
165
  selectedIds,
149
166
  newItem.id,
150
- depth + 1
167
+ depth + 1,
168
+ isDisabled
151
169
  );
152
170
  }
153
171
  return newItem;
@@ -244,8 +262,9 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
244
262
  return tree.map((item: any) => {
245
263
  if (item.id != id) item.children = modifyValue(id, item.children, check);
246
264
  else {
247
- item.checked = check;
248
-
265
+ if (!item.disabled) {
266
+ item.checked = check;
267
+ }
249
268
  if (variant === "single") {
250
269
  // Single select: no children should be checked
251
270
  item.children = modifyRecursive(item.children, !check);
@@ -430,6 +449,12 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
430
449
  className={classes}
431
450
  id={id}
432
451
  >
452
+ {label &&
453
+ <Caption
454
+ marginBottom="xs"
455
+ text={label}
456
+ />
457
+ }
433
458
  <MultiLevelSelectContext.Provider value={{
434
459
  variant,
435
460
  inputName,
@@ -453,6 +478,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
453
478
  disabled={disabled}
454
479
  key={selectedItem.id}
455
480
  name={`${name}[]`}
481
+ required={required}
456
482
  type="hidden"
457
483
  value={selectedItem.id}
458
484
  />
@@ -467,6 +493,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
467
493
  disabled={disabled}
468
494
  key={item.id}
469
495
  name={`${name}[]`}
496
+ required={required}
470
497
  type="hidden"
471
498
  value={item.id}
472
499
  />
@@ -479,6 +506,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
479
506
  disabled={disabled}
480
507
  key={item.id}
481
508
  name={`${name}[]`}
509
+ required={required}
482
510
  type="hidden"
483
511
  value={item.id}
484
512
  />
@@ -539,6 +567,7 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
539
567
  } selected`
540
568
  : "Start typing..."
541
569
  }
570
+ required={required}
542
571
  value={singleSelectedItem.value || filterItem}
543
572
  />
544
573
  </div>
@@ -571,6 +600,13 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
571
600
  </div>
572
601
  </div>
573
602
  </MultiLevelSelectContext.Provider>
603
+ {error &&
604
+ <Body
605
+ dark={props.dark}
606
+ status="negative"
607
+ text={error}
608
+ />
609
+ }
574
610
  </div>
575
611
  );
576
612
  }) as MultiLevelSelectComponent;
@@ -66,7 +66,7 @@
66
66
 
67
67
  <%= pb_rails("multi_level_select", props: {
68
68
  disabled: true,
69
- id: "multi-level-select-default-rails",
69
+ id: "multi-level-select-disabled-rails",
70
70
  name: "my_array",
71
71
  tree_data: treeData
72
72
  }) %>