playbook_ui 14.15.0.pre.rc.3 → 14.15.0

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +127 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +55 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TablePagination.tsx +33 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +275 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +143 -3
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +66 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +195 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +45 -99
  10. data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +73 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowUtils.ts +52 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/Utilities/TableContainerStyles.ts +80 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +123 -7
  14. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +153 -299
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +50 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_infinite_scroll.json +152002 -0
  17. data/app/pb_kits/playbook/pb_card/_card.tsx +2 -1
  18. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +4 -1
  19. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +2 -0
  20. data/app/pb_kits/playbook/pb_date_picker/index.ts +38 -0
  21. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +19 -3
  22. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +3 -3
  23. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +20 -37
  24. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +6 -6
  25. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +1 -0
  26. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -0
  27. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +5 -4
  28. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +2 -2
  29. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -1
  30. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +9 -2
  31. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +4 -0
  32. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.html.erb +40 -0
  33. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.jsx +50 -0
  34. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_wrapped.md +3 -0
  35. data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +2 -0
  36. data/app/pb_kits/playbook/pb_form_pill/docs/index.js +1 -0
  37. data/app/pb_kits/playbook/pb_form_pill/form_pill.rb +7 -1
  38. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +7 -0
  39. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +13 -3
  40. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +72 -0
  41. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +91 -0
  42. data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +2 -1
  43. data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +1 -0
  44. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +6 -0
  45. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +13 -0
  46. data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +7 -1
  47. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.html.erb +11 -0
  48. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.jsx +37 -0
  49. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_rails.md +1 -0
  50. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_react.md +1 -0
  51. data/app/pb_kits/playbook/pb_overlay/docs/example.yml +2 -0
  52. data/app/pb_kits/playbook/pb_overlay/docs/index.js +1 -0
  53. data/app/pb_kits/playbook/pb_overlay/overlay.rb +7 -1
  54. data/app/pb_kits/playbook/pb_overlay/overlay.test.jsx +12 -0
  55. data/app/pb_kits/playbook/pb_popover/_popover.tsx +1 -1
  56. data/app/pb_kits/playbook/pb_radio/_radio.tsx +85 -74
  57. data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.jsx +60 -0
  58. data/app/pb_kits/playbook/pb_radio/docs/_radio_react_hook.md +1 -0
  59. data/app/pb_kits/playbook/pb_radio/docs/example.yml +2 -1
  60. data/app/pb_kits/playbook/pb_radio/docs/index.js +1 -0
  61. data/app/pb_kits/playbook/pb_radio/radio.test.js +16 -0
  62. data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.jsx +58 -0
  63. data/app/pb_kits/playbook/pb_select/docs/_select_react_hook.md +1 -0
  64. data/app/pb_kits/playbook/pb_select/docs/example.yml +1 -0
  65. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  66. data/app/pb_kits/playbook/pb_select/select.html.erb +3 -5
  67. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +1 -5
  68. data/app/pb_kits/playbook/pb_selectable_card_icon/selectable_card_icon.html.erb +1 -4
  69. data/app/pb_kits/playbook/pb_selectable_icon/selectable_icon.html.erb +1 -5
  70. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +2 -2
  71. data/app/pb_kits/playbook/pb_title/_title.scss +32 -0
  72. data/app/pb_kits/playbook/pb_title/_title.tsx +10 -1
  73. data/app/pb_kits/playbook/pb_title/docs/_title_default.html.erb +1 -2
  74. data/app/pb_kits/playbook/pb_title/docs/_title_default.jsx +1 -1
  75. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.html.erb +7 -0
  76. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.jsx +54 -0
  77. data/app/pb_kits/playbook/pb_title/docs/_title_display_size.md +1 -0
  78. data/app/pb_kits/playbook/pb_title/docs/example.yml +2 -0
  79. data/app/pb_kits/playbook/pb_title/docs/index.js +1 -0
  80. data/app/pb_kits/playbook/pb_title/title.rb +10 -1
  81. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +25 -0
  82. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.jsx +69 -0
  83. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_sizing.md +3 -0
  84. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +1 -1
  85. data/app/pb_kits/playbook/pb_tooltip/docs/index.js +1 -0
  86. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +36 -2
  87. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +5 -1
  88. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options.html.erb +45 -0
  89. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options.md +5 -0
  90. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options_pure_rails.html.erb +33 -0
  91. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_dynamic_options_pure_rails.md +3 -0
  92. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
  93. data/app/pb_kits/playbook/pb_typeahead/index.ts +61 -8
  94. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +17 -2
  95. data/app/pb_kits/playbook/utilities/object.test.js +99 -0
  96. data/app/pb_kits/playbook/utilities/object.ts +29 -1
  97. data/dist/chunks/_typeahead-BhfaW1J9.js +36 -0
  98. data/dist/chunks/_weekday_stacked-CKRIELiF.js +45 -0
  99. data/dist/chunks/lazysizes-DHz07jlL.js +1 -0
  100. data/dist/chunks/{lib-Fr78pbpF.js → lib-5OzNgeeu.js} +2 -2
  101. data/dist/chunks/{pb_form_validation-CN51bfsD.js → pb_form_validation-DGhKbZtO.js} +1 -1
  102. data/dist/chunks/vendor.js +1 -1
  103. data/dist/playbook-doc.js +1 -1
  104. data/dist/playbook-rails-react-bindings.js +1 -1
  105. data/dist/playbook-rails.js +1 -1
  106. data/dist/playbook.css +1 -1
  107. data/lib/playbook/version.rb +1 -1
  108. metadata +42 -7
  109. data/dist/chunks/_typeahead-BGTMEmj7.js +0 -36
  110. data/dist/chunks/_weekday_stacked-De2TduOp.js +0 -45
  111. data/dist/chunks/lazysizes-B7xYodB-.js +0 -1
@@ -1,7 +1,8 @@
1
1
  /* eslint-disable react/no-multi-comp */
2
2
 
3
3
  import React from 'react'
4
- import { get } from 'lodash'
4
+ import { get } from '../utilities/object'
5
+
5
6
  import classnames from 'classnames'
6
7
 
7
8
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
@@ -1,5 +1,8 @@
1
1
  <%= pb_content_tag(:div,
2
- class: object.classname + object.error_class) do %>
2
+ class: object.classname + object.error_class,
3
+ 'data-pb-date-picker' => true,
4
+ 'data-validation-message' => object.validation_message,
5
+ ) do %>
3
6
  <div class="input_wrapper">
4
7
  <% if content.present? %>
5
8
  <%= content %>
@@ -75,6 +75,8 @@ module Playbook
75
75
  default: [1900, 2100]
76
76
  prop :custom_event_type, type: Playbook::Props::String,
77
77
  default: ""
78
+ prop :validation_message, type: Playbook::Props::String,
79
+ default: ""
78
80
 
79
81
  def classname
80
82
  default_margin_bottom = margin_bottom.present? ? "" : " mb_sm"
@@ -0,0 +1,38 @@
1
+ import PbEnhancedElement from "../pb_enhanced_element";
2
+
3
+ const DATE_PICKER_WRAPPER_SELECTOR = '[data-pb-date-picker]';
4
+ const SELECT_VALIDATION_MESSAGE_CLASS = '.pb_body_kit_negative';
5
+
6
+ export default class PbDatePicker extends PbEnhancedElement {
7
+ static get selector() {
8
+ return DATE_PICKER_WRAPPER_SELECTOR;
9
+ }
10
+
11
+ connect() {
12
+ this.setValidationMessage();
13
+ }
14
+
15
+ setValidationMessage() {
16
+ const validationMessage = this.element.dataset?.validationMessage;
17
+ const inputElement = this.element.querySelector("input");
18
+
19
+ if (validationMessage) {
20
+ const setErrorTextContent = (text, timeout) => {
21
+ setTimeout(() => {
22
+ const errorMessageElement = this.element.querySelector(SELECT_VALIDATION_MESSAGE_CLASS);
23
+ if (errorMessageElement) {
24
+ errorMessageElement.textContent = text;
25
+ } else {
26
+ setErrorTextContent(text, 100);
27
+ }
28
+ }, timeout);
29
+ };
30
+
31
+ inputElement.addEventListener("change", (e) => {
32
+ if (!e.target.checkValidity()) {
33
+ setErrorTextContent(validationMessage, 300);
34
+ }
35
+ });
36
+ }
37
+ }
38
+ }
@@ -134,6 +134,14 @@ body.PBDrawer__Body--close {
134
134
  transition: margin-left $animation-duration ease-out, margin-right $animation-duration ease-out;
135
135
  }
136
136
 
137
+ .pb_drawer_lg_left .pb_drawer {
138
+ transform: translateX(-100%);
139
+ }
140
+
141
+ .pb_drawer_lg_right .pb_drawer {
142
+ transform: translateX(100%);
143
+ }
144
+
137
145
  .pb_drawer.pb_drawer_after_open {
138
146
  pointer-events: auto;
139
147
  transform: translate3d(0, 0, 0);
@@ -317,7 +325,6 @@ body.PBDrawer__Body--close {
317
325
  display: flex;
318
326
  background-color: rgba($bg_dark, $opacity_4);
319
327
  z-index: $z-index;
320
- opacity: 0;
321
328
  animation: overlayFade $animation-duration ease-in-out forwards;
322
329
 
323
330
  &[class*="_left"]{
@@ -345,12 +352,21 @@ body.PBDrawer__Body--close {
345
352
  left: 0;
346
353
  right: 0;
347
354
  bottom: 0;
355
+ display: flex;
348
356
  z-index: $z-index;
349
357
  opacity: 1;
350
358
  pointer-events: none;
351
359
 
352
- & .pb_drawer {
353
- pointer-events: auto;
360
+ &[class*="_right"]{
361
+ justify-content: flex-end;
362
+ }
363
+
364
+ &[class*="_left"]{
365
+ justify-content: flex-start;
366
+ }
367
+
368
+ &[class*="_center"]{
369
+ justify-content: center;
354
370
  }
355
371
 
356
372
  &_before_close {
@@ -41,7 +41,7 @@ const DrawerBorders = () => {
41
41
  onClose={toggleBRightDrawer}
42
42
  opened={openedBRightDrawer}
43
43
  overlay={false}
44
- placement="left"
44
+ placement="right"
45
45
  size="lg"
46
46
  >
47
47
  This is a Drawer with border right
@@ -52,7 +52,7 @@ const DrawerBorders = () => {
52
52
  onClose={toggleBLeftDrawer}
53
53
  opened={openedBLeftDrawer}
54
54
  overlay={false}
55
- placement="left"
55
+ placement="right"
56
56
  size="lg"
57
57
  >
58
58
  This is a Drawer with border left
@@ -63,7 +63,7 @@ const DrawerBorders = () => {
63
63
  onClose={toggleBFullDrawer}
64
64
  opened={openedBFullDrawer}
65
65
  overlay={false}
66
- placement="left"
66
+ placement="right"
67
67
  size="lg"
68
68
  >
69
69
  This is a Drawer with border full
@@ -1,42 +1,25 @@
1
- import React, { useState } from "react";
2
- import { Button, Drawer, Flex } from "playbook-ui";
3
-
4
- const useDrawer = (visible = false) => {
5
- const [opened, setOpened] = useState(visible);
6
- const toggle = () => setOpened(!opened);
7
-
8
- return [opened, toggle];
9
- };
10
-
11
- const DrawerBreakpoints = () => {
12
- const [smallDrawerOpened, toggleSmallDrawer] = useDrawer();
1
+ import React from "react"
2
+ import { Button, Body } from "playbook-ui"
13
3
 
4
+ const DrawerMenu = () => {
14
5
  return (
15
6
  <>
16
- <Flex wrap>
17
- <Button
18
- id="sm"
19
- marginRight="md"
20
- onClick={toggleSmallDrawer}
21
- >
22
- {"Will open at small breakpoint"}
23
- </Button>
24
- </Flex>
25
- <Flex>
26
- <Drawer
27
- behavior={"push"}
28
- breakpoint="sm"
29
- onClose={toggleSmallDrawer}
30
- opened={smallDrawerOpened}
31
- overlay={false}
32
- placement={"right"}
33
- size={"lg"}
34
- >
35
- Open because small breakpoint
36
- </Drawer>
37
- </Flex>
7
+ <Body>
8
+ The breakpoint prop determines when the Drawer is always visible. Above
9
+ the specified breakpoint, the Drawer remains open on the page. Below it,
10
+ only the trigger element is shown, allowing you to toggle the drawer
11
+ open and closed. To see this in action, click the button below and
12
+ resize your window.
13
+ </Body>
14
+ <Button
15
+ link='https://8njdkc.csb.app/'
16
+ marginTop='md'
17
+ newWindow
18
+ >
19
+ Open Doc Example in New Tab
20
+ </Button>
38
21
  </>
39
- );
40
- };
22
+ )
23
+ }
41
24
 
42
- export default DrawerBreakpoints;
25
+ export default DrawerMenu
@@ -8,8 +8,8 @@ const DrawerMenu = () => {
8
8
  const mediaQuery = window.matchMedia("(max-width: 600px)")
9
9
  setIsSmallScreen(mediaQuery.matches)
10
10
  const handler = (e) => setIsSmallScreen(e.matches)
11
- mediaQuery.addEventListener('change', handler)
12
- return () => mediaQuery.removeEventListener('change', handler)
11
+ mediaQuery.addEventListener("change", handler)
12
+ return () => mediaQuery.removeEventListener("change", handler)
13
13
  }, [])
14
14
 
15
15
  return (
@@ -22,17 +22,17 @@ const DrawerMenu = () => {
22
22
  />
23
23
  </Button>
24
24
  <Drawer
25
- breakpoint="md"
25
+ breakpoint='md'
26
26
  placement='bottom'
27
27
  size='full'
28
28
  triggerId='menuButton'
29
29
  withinElement
30
30
  >
31
- <Nav
31
+ <Nav
32
32
  highlight={false}
33
33
  link='#'
34
- orientation={isSmallScreen ? 'vertical' : 'horizontal'}
35
- padding={isSmallScreen ? 'none' : 'sm'}
34
+ orientation={isSmallScreen ? "vertical" : "horizontal"}
35
+ padding={isSmallScreen ? "none" : "sm"}
36
36
  >
37
37
  <NavItem link='#'
38
38
  text='About'
@@ -31,6 +31,7 @@ const DrawerSizes = () => {
31
31
  onClose={toggleNoOverlayDrawer}
32
32
  opened={openedNoOverlayDrawer}
33
33
  overlay={false}
34
+ placement='right'
34
35
  size='lg'
35
36
  >
36
37
  This is a Drawer with no overlay
@@ -15,4 +15,5 @@ examples:
15
15
  - drawer_menu: Within Element
16
16
  - drawer_sizes: Sizes
17
17
  - drawer_overlay: Overlay
18
+ - drawer_breakpoints: Breakpoints
18
19
  - drawer_borders: Borders
@@ -1,5 +1,6 @@
1
1
  import React from 'react'
2
- import { isEmpty, map, omitBy } from 'lodash'
2
+ import { map } from 'lodash'
3
+ import { isEmpty, omitBy } from '../../utilities/object'
3
4
 
4
5
  import Body from '../../pb_body/_body'
5
6
  import Caption from '../../pb_caption/_caption'
@@ -40,13 +41,13 @@ const CurrentFilters = ({ dark, filters }: CurrentFiltersProps): React.ReactElem
40
41
  className="filter"
41
42
  key={`filter-${name}`}
42
43
  >
43
- { value === true ?
44
+ { value === true ?
44
45
  <Title
45
46
  dark={dark}
46
47
  size={4}
47
48
  tag="h4"
48
49
  text={name}
49
- /> :
50
+ /> :
50
51
  <div>
51
52
  <Caption
52
53
  dark={dark}
@@ -58,7 +59,7 @@ const CurrentFilters = ({ dark, filters }: CurrentFiltersProps): React.ReactElem
58
59
  tag="h4"
59
60
  text={value}
60
61
  />
61
- </div>
62
+ </div>
62
63
  }
63
64
  </div>
64
65
  ))}
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { isEmpty } from 'lodash'
2
+ import { isEmpty } from '../../utilities/object'
3
3
 
4
4
  import Flex from '../../pb_flex/_flex'
5
5
 
@@ -46,7 +46,7 @@ const FilterSingle = ({
46
46
  paddingRight="lg"
47
47
  vertical="center"
48
48
  >
49
- { children &&
49
+ { children &&
50
50
  <>
51
51
  <FiltersPopover
52
52
  dark={dark}
@@ -35,7 +35,7 @@
35
35
  <%= form.select :example_select_validation, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true, validation_message: "Please, select an option." } %>
36
36
  <%= form.collection_select :example_collection_select_validation, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
37
37
  <%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
38
- <%= form.date_picker :example_date_picker_2, props: { label: true, required: true } %>
38
+ <%= form.date_picker :example_date_picker_2, props: { label: true, required: true, validation_message: "Please, select a date.", allow_input: true } %>
39
39
  <%= form.star_rating_field :example_star_rating_validation, props: { variant: "interactive", label: true, required: true } %>
40
40
  <%= 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 } %>
41
41
 
@@ -23,6 +23,13 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
23
23
  .pb_form_pill_text, .pb_form_pill_close, .pb_form_pill_tag{
24
24
  font-size: $font_small !important;
25
25
  }
26
+
27
+ &[class*=wrapped] {
28
+ height: max-content;
29
+ padding-top: $space-xxs;
30
+ padding-bottom: $space-xxs;
31
+ }
32
+
26
33
  @each $color_name, $color_value in $form_pill_colors {
27
34
  &[class*=_#{$color_name}] {
28
35
  background-color: mix($color_value, $card_light, 10%);
@@ -142,7 +149,7 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
142
149
  height: 12px !important;
143
150
  width: 12px !important;
144
151
  padding-right: $space_xs;
145
- + .pb_form_pill_text, + .pb_form_pill_tag,
152
+ + .pb_form_pill_text, + .pb_form_pill_tag,
146
153
  + .pb_tooltip_kit .pb_form_pill_text, + .pb_tooltip_kit .pb_form_pill_tag,
147
154
  + div .pb_form_pill_text, + div .pb_form_pill_tag {
148
155
  padding-left: 0;
@@ -171,7 +178,7 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
171
178
  }
172
179
  .pb_form_pill_icon {
173
180
  padding-right: $space_xxs;
174
- + .pb_form_pill_text, + .pb_form_pill_tag,
181
+ + .pb_form_pill_text, + .pb_form_pill_tag,
175
182
  + .pb_tooltip_kit .pb_form_pill_text, + .pb_tooltip_kit .pb_form_pill_tag,
176
183
  + div .pb_form_pill_text, + div .pb_form_pill_tag {
177
184
  padding-left: 0;
@@ -22,6 +22,7 @@ type FormPillProps = {
22
22
  data?: {[key: string]: string},
23
23
  tabIndex?: number,
24
24
  icon?: string,
25
+ wrapped?: boolean,
25
26
  closeProps?: {
26
27
  onClick?: React.MouseEventHandler<HTMLSpanElement>,
27
28
  onMouseDown?: React.MouseEventHandler<HTMLSpanElement>,
@@ -38,6 +39,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
38
39
  onClick = () => undefined,
39
40
  avatarUrl,
40
41
  closeProps = {},
42
+ wrapped,
41
43
  size = '',
42
44
  textTransform = 'none',
43
45
  color = "primary",
@@ -48,6 +50,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
48
50
 
49
51
  const iconClass = icon ? "_icon" : ""
50
52
  const closeIconSize = size === "small" ? "xs" : "sm"
53
+ const wrappedClass = wrapped ? "wrapped" : ""
51
54
 
52
55
  const filteredProps: FormPillProps = {...props}
53
56
  delete filteredProps.truncate
@@ -55,6 +58,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
55
58
  const css = classnames(
56
59
  `pb_form_pill_kit_${color}${iconClass}`,
57
60
  globalProps(filteredProps),
61
+ wrappedClass,
58
62
  className,
59
63
  size === 'small' ? 'small' : null,
60
64
  textTransform,
@@ -0,0 +1,40 @@
1
+ <%
2
+ names = [
3
+ { label: 'Alexander Nathaniel Montgomery', value: 'Alexander Nathaniel Montgomery' },
4
+ { label: 'Isabella Anastasia Wellington', value: 'Isabella Anastasia Wellington' },
5
+ { label: 'Christopher Maximilian Harrington', value: 'Christopher Maximilian Harrington' },
6
+ { label: 'Elizabeth Seraphina Kensington', value: 'Elizabeth Seraphina Kensington' },
7
+ { label: 'Theodore Jonathan Abernathy', value: 'Theodore Jonathan Abernathy' },
8
+ ]
9
+ %>
10
+
11
+ <%= pb_rails("typeahead", props: {
12
+ html_options: { style: { maxWidth: "240px" }},
13
+ id: "typeahead-form-pill",
14
+ is_multi: true,
15
+ options: names,
16
+ label: "Wrapped Within Typeahead",
17
+ pills: true,
18
+ wrapped: true,
19
+ }) %>
20
+
21
+ <%= pb_rails("caption", props: { text: "Form Pill Wrapped Text" }) %>
22
+ <%= pb_rails("card", props: { max_width: "xs" }) do %>
23
+ <%= pb_rails("form_pill", props: {
24
+ name: "Princess Amelia Mignonette Grimaldi Thermopolis Renaldo",
25
+ avatar_url: "https://randomuser.me/api/portraits/women/44.jpg",
26
+ tabindex: 0,
27
+ wrapped: true,
28
+ }) %>
29
+ <%= pb_rails("form_pill", props: {
30
+ icon: "badge-check",
31
+ text: "icon and a very long tag to show wrapped text",
32
+ tabindex: 0,
33
+ wrapped: true,
34
+ }) %>
35
+ <%= pb_rails("form_pill", props: {
36
+ text: "form pill long tag no tooltip show wrapped text",
37
+ tabindex: 0,
38
+ wrapped: true,
39
+ }) %>
40
+ <% end %>
@@ -0,0 +1,50 @@
1
+ import React from 'react'
2
+ import { Card, Caption, FormPill, Typeahead } from 'playbook-ui'
3
+
4
+ const names = [
5
+ { label: 'Alexander Nathaniel Montgomery', value: 'Alexander Nathaniel Montgomery' },
6
+ { label: 'Isabella Anastasia Wellington', value: 'Isabella Anastasia Wellington' },
7
+ { label: 'Christopher Maximilian Harrington', value: 'Christopher Maximilian Harrington' },
8
+ { label: 'Elizabeth Seraphina Kensington', value: 'Elizabeth Seraphina Kensington' },
9
+ { label: 'Theodore Jonathan Abernathy', value: 'Theodore Jonathan Abernathy' },
10
+ ]
11
+
12
+ const FormPillWrapped = (props) => {
13
+ return (
14
+ <>
15
+ <Typeahead
16
+ htmlOptions={{ style: { maxWidth: "240px" } }}
17
+ isMulti
18
+ label="Wrapped Within Typeahead"
19
+ options={names}
20
+ wrapped
21
+ {...props}
22
+ />
23
+ <Caption text="Form Pill Wrapped Text"/>
24
+ <Card maxWidth="xs">
25
+ <FormPill
26
+ avatarUrl="https://randomuser.me/api/portraits/women/44.jpg"
27
+ name="Princess Amelia Mignonette Grimaldi Thermopolis Renaldo"
28
+ onClick={() => alert('Click!')}
29
+ tabIndex={0}
30
+ wrapped
31
+ />
32
+ <FormPill
33
+ icon="badge-check"
34
+ onClick={() => {alert('Click!')}}
35
+ tabIndex={0}
36
+ text="icon and a very long tag to show wrapped text"
37
+ wrapped
38
+ />
39
+ <FormPill
40
+ onClick={() => {alert('Click!')}}
41
+ tabIndex={0}
42
+ text="form pill with a very long tag to show wrapped text"
43
+ wrapped
44
+ />
45
+ </Card>
46
+ </>
47
+ )
48
+ }
49
+
50
+ export default FormPillWrapped
@@ -0,0 +1,3 @@
1
+ For Form Pills with longer text, the `wrapped` prop can be used to wrap the label within each Form Pill.
2
+
3
+ **Note**: Avoid using the `wrapped` and `small` props together, as their styles conflict and may cause functionality issues.
@@ -4,6 +4,7 @@ examples:
4
4
  - form_pill_user: Form Pill User
5
5
  - form_pill_size: Form Pill Size
6
6
  - form_pill_truncated_text: Truncated Text
7
+ - form_pill_wrapped: Wrapped Text
7
8
  - form_pill_tag: Form Pill Tag
8
9
  - form_pill_example: Example
9
10
  - form_pill_icon: Form Pill Icon
@@ -13,6 +14,7 @@ examples:
13
14
  - form_pill_user: Form Pill User
14
15
  - form_pill_size: Form Pill Size
15
16
  - form_pill_truncated_text: Truncated Text
17
+ - form_pill_wrapped: Wrapped Text
16
18
  - form_pill_tag: Form Pill Tag
17
19
  - form_pill_example: Example
18
20
  - form_pill_icon: Form Pill Icon
@@ -5,3 +5,4 @@ export { default as FormPillExample } from './_form_pill_example.jsx'
5
5
  export { default as FormPillIcon } from './_form_pill_icon.jsx'
6
6
  export { default as FormPillColors } from './_form_pill_colors.jsx'
7
7
  export { default as FormPillTruncatedText } from './_form_pill_truncated_text.jsx'
8
+ export { default as FormPillWrapped } from './_form_pill_wrapped.jsx'
@@ -16,9 +16,11 @@ module Playbook
16
16
  default: "primary"
17
17
  prop :tabindex
18
18
  prop :icon
19
+ prop :wrapped, type: Playbook::Props::Boolean,
20
+ default: false
19
21
 
20
22
  def classname
21
- generate_classname("pb_form_pill_kit", color, icon_class, name, text, text_transform)
23
+ generate_classname("pb_form_pill_kit", color, icon_class, name, text, text_transform, wrapped_class)
22
24
  end
23
25
 
24
26
  def display_text
@@ -36,6 +38,10 @@ module Playbook
36
38
  def close_icon_size
37
39
  size == "small" ? "xs" : "sm"
38
40
  end
41
+
42
+ def wrapped_class
43
+ wrapped ? "wrapped" : nil
44
+ end
39
45
  end
40
46
  end
41
47
  end
@@ -42,6 +42,13 @@
42
42
  outline: none;
43
43
  }
44
44
  }
45
+
46
+ &:has(input:disabled) {
47
+ background-color: shade($white, 5%);
48
+ box-shadow: none;
49
+ cursor: default;
50
+ opacity: 0.5;
51
+ }
45
52
  }
46
53
  }
47
54
  .dropdown_menu {
@@ -27,6 +27,7 @@ type MultiLevelSelectProps = {
27
27
  aria?: { [key: string]: string }
28
28
  className?: string
29
29
  data?: { [key: string]: string }
30
+ disabled?: boolean
30
31
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
31
32
  id?: string
32
33
  inputDisplay?: "pills" | "none"
@@ -37,6 +38,7 @@ type MultiLevelSelectProps = {
37
38
  onSelect?: (prop: { [key: string]: any }) => void
38
39
  selectedIds?: string[] | any
39
40
  variant?: "multi" | "single"
41
+ wrapped?: boolean
40
42
  pillColor?: "primary" | "neutral" | "success" | "warning" | "error" | "info" | "data_1" | "data_2" | "data_3" | "data_4" | "data_5" | "data_6" | "data_7" | "data_8" | "windows" | "siding" | "roofing" | "doors" | "gutters" | "solar" | "insulation" | "accessories",
41
43
  } & GlobalProps
42
44
 
@@ -45,6 +47,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
45
47
  aria = {},
46
48
  className,
47
49
  data = {},
50
+ disabled = false,
48
51
  htmlOptions = {},
49
52
  id,
50
53
  inputDisplay = "pills",
@@ -56,6 +59,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
56
59
  selectedIds,
57
60
  variant = "multi",
58
61
  children,
62
+ wrapped,
59
63
  pillColor = "primary"
60
64
  } = props
61
65
 
@@ -292,7 +296,8 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
292
296
  const handleInputWrapperClick = (e: any) => {
293
297
  if (
294
298
  e.target.id === "multiselect_input" ||
295
- e.target.classList.contains("pb_form_pill_tag")
299
+ e.target.classList.contains("pb_form_pill_tag") ||
300
+ disabled
296
301
  ) {
297
302
  return;
298
303
  }
@@ -421,16 +426,17 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
421
426
  handledropdownItemClick,
422
427
  filterItem,
423
428
  }}>
424
- <div className="wrapper"
429
+ <div className="wrapper"
425
430
  ref={dropdownRef}
426
431
  >
427
- <div className="input_wrapper"
432
+ <div className="input_wrapper"
428
433
  onClick={handleInputWrapperClick}
429
434
  >
430
435
  <div className="input_inner_container">
431
436
  {variant === "single" && defaultReturn.length !== 0
432
437
  ? defaultReturn.map((selectedItem) => (
433
438
  <input
439
+ disabled={disabled}
434
440
  key={selectedItem.id}
435
441
  name={`${name}[]`}
436
442
  type="hidden"
@@ -444,6 +450,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
444
450
  {returnAllSelected && returnedArray.length !== 0
445
451
  ? returnedArray.map((item) => (
446
452
  <input
453
+ disabled={disabled}
447
454
  key={item.id}
448
455
  name={`${name}[]`}
449
456
  type="hidden"
@@ -461,6 +468,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
461
468
  key={index}
462
469
  onClick={(event: any) => handlePillClose(event, item)}
463
470
  text={item.label}
471
+ wrapped={wrapped}
464
472
  />
465
473
  ))
466
474
  : null}
@@ -474,6 +482,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
474
482
  key={index}
475
483
  onClick={(event: any) => handlePillClose(event, item)}
476
484
  text={item.label}
485
+ wrapped={wrapped}
477
486
  />
478
487
  ))
479
488
  : null}
@@ -489,6 +498,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
489
498
  )}
490
499
 
491
500
  <input
501
+ disabled={disabled}
492
502
  id="multiselect_input"
493
503
  onChange={(e) => {
494
504
  variant === "single"