playbook_ui 12.29.0.pre.alpha.play716popoverkitcloseonclickissue893 → 12.30.0.pre.alpha.PLAY906multilevelselectedidsprop902

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_icon/_icon.tsx +27 -1
  3. data/app/pb_kits/playbook/pb_icon/icon.html.erb +2 -0
  4. data/app/pb_kits/playbook/pb_icon/icon.rb +5 -0
  5. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.scss +5 -0
  6. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.tsx +5 -3
  7. data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_color.html.erb +13 -7
  8. data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_default.html.erb +1 -1
  9. data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_emoji.html.erb +16 -0
  10. data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_emoji.jsx +31 -0
  11. data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_emoji.md +1 -0
  12. data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_sizes.html.erb +5 -5
  13. data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_sizes.jsx +6 -0
  14. data/app/pb_kits/playbook/pb_icon_circle/docs/example.yml +3 -0
  15. data/app/pb_kits/playbook/pb_icon_circle/docs/index.js +1 -0
  16. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.html.erb +1 -1
  17. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.rb +2 -0
  18. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.test.js +97 -0
  19. data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +56 -27
  20. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +1 -2
  21. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +19 -31
  22. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.md +3 -1
  23. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +7 -0
  24. data/app/pb_kits/playbook/pb_popover/_popover.tsx +3 -5
  25. data/app/pb_kits/playbook/pb_popover/index.ts +2 -5
  26. data/app/pb_kits/playbook/pb_table/docs/_table_data_table.html.erb +0 -14
  27. data/app/pb_kits/playbook/pb_table/docs/_table_data_table.md +1 -0
  28. data/app/pb_kits/playbook/pb_table/styles/_structure.scss +12 -0
  29. data/app/pb_kits/playbook/utilities/globalProps.ts +9 -4
  30. data/app/pb_kits/playbook/utilities/test/globalProps/flexGrow.test.js +1 -1
  31. data/app/pb_kits/playbook/utilities/test/globalProps/flexShrink.test.js +1 -1
  32. data/dist/playbook-rails.js +6 -6
  33. data/lib/playbook/version.rb +2 -2
  34. metadata +7 -2
@@ -15,6 +15,7 @@ import {
15
15
  getCheckedItems,
16
16
  getDefaultCheckedItems,
17
17
  recursiveCheckParent,
18
+ getExpandedItems,
18
19
  } from "./_helper_functions"
19
20
 
20
21
  type MultiLevelSelectProps = {
@@ -22,10 +23,12 @@ type MultiLevelSelectProps = {
22
23
  className?: string
23
24
  data?: { [key: string]: string }
24
25
  id?: string
26
+ inputDisplay?: "pills" | "none"
25
27
  name?: string
26
28
  returnAllSelected?: boolean
27
29
  treeData?: { [key: string]: string }[]
28
30
  onSelect?: (prop: { [key: string]: any }) => void
31
+ selectedIds?: string[]
29
32
  } & GlobalProps
30
33
 
31
34
  const MultiLevelSelect = (props: MultiLevelSelectProps) => {
@@ -34,10 +37,12 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
34
37
  className,
35
38
  data = {},
36
39
  id,
40
+ inputDisplay = "pills",
37
41
  name,
38
42
  returnAllSelected = false,
39
43
  treeData,
40
44
  onSelect = () => {},
45
+ selectedIds
41
46
  } = props
42
47
 
43
48
  const ariaProps = buildAriaProps(aria)
@@ -50,26 +55,6 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
50
55
 
51
56
  const dropdownRef = useRef(null)
52
57
 
53
-
54
- const getExpandedItems = (treeData: { [key: string]: string }[]) => {
55
- let expandedItems: any[] = [];
56
-
57
- const traverse = (items: string | any[]) => {
58
- for (let i = 0; i < items.length; i++) {
59
- const item = items[i];
60
- if (item.expanded) {
61
- expandedItems.push(item.id);
62
- }
63
- if (Array.isArray(item.children)) {
64
- traverse(item.children);
65
- }
66
- }
67
- }
68
-
69
- traverse(treeData);
70
- return expandedItems;
71
- }
72
-
73
58
  //state for whether dropdown is open or closed
74
59
  const [isClosed, setIsClosed] = useState(true)
75
60
  //state from onchange for textinput, to use for filtering to create typeahead
@@ -87,8 +72,8 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
87
72
 
88
73
 
89
74
  useEffect(() => {
90
- setFormattedData(addCheckedAndParentProperty(treeData))
91
- }, [treeData])
75
+ setFormattedData(addCheckedAndParentProperty(treeData, selectedIds))
76
+ }, [treeData, selectedIds])
92
77
 
93
78
  useEffect(() => {
94
79
  if (returnAllSelected) {
@@ -174,11 +159,10 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
174
159
  return tree
175
160
  }
176
161
 
177
-
178
-
179
162
  //function to map over data and add parent_id + depth property to each item
180
163
  const addCheckedAndParentProperty = (
181
164
  treeData: { [key: string]: any }[],
165
+ selectedIds: string[],
182
166
  parent_id: string = null,
183
167
  depth: number = 0,
184
168
  ) => {
@@ -188,6 +172,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
188
172
  return treeData.map((item: { [key: string]: any } | any) => {
189
173
  const newItem = {
190
174
  ...item,
175
+ checked: selectedIds && selectedIds.length && selectedIds.includes(item.id),
191
176
  parent_id,
192
177
  depth,
193
178
  }
@@ -198,6 +183,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
198
183
  : item.children
199
184
  newItem.children = addCheckedAndParentProperty(
200
185
  children,
186
+ selectedIds,
201
187
  newItem.id,
202
188
  depth + 1
203
189
  )
@@ -331,7 +317,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
331
317
  ))
332
318
  : null}
333
319
 
334
- {returnedArray.length !== 0 && returnAllSelected
320
+ {returnedArray.length !== 0 && inputDisplay === "pills" && returnAllSelected
335
321
  ? returnedArray.map((item, index) => (
336
322
  <FormPill
337
323
  key={index}
@@ -342,7 +328,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
342
328
  ))
343
329
  : null}
344
330
  {!returnAllSelected &&
345
- defaultReturn.length !== 0 &&
331
+ defaultReturn.length !== 0 && inputDisplay === "pills" ?
346
332
  defaultReturn.map((item, index) => (
347
333
  <FormPill
348
334
  key={index}
@@ -350,9 +336,11 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
350
336
  size='small'
351
337
  onClick={(event: any) => handlePillClose(event, item)}
352
338
  />
353
- ))}
354
- {returnedArray.length !== 0 && returnAllSelected && <br />}
355
- {defaultReturn.length !== 0 && !returnAllSelected && <br />}
339
+ ))
340
+ : null
341
+ }
342
+ {returnedArray.length !== 0 && returnAllSelected && inputDisplay === "pills" && <br />}
343
+ {defaultReturn.length !== 0 && !returnAllSelected && inputDisplay === "pills" && <br />}
356
344
  <input
357
345
  id='multiselect_input'
358
346
  onChange={(e) => {
@@ -365,11 +353,11 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
365
353
  </div>
366
354
  {isClosed ? (
367
355
  <div key='chevron-down'>
368
- <Icon icon='chevron-down' />
356
+ <Icon icon='chevron-down' size="xs"/>
369
357
  </div>
370
358
  ) : (
371
359
  <div key='chevron-up'>
372
- <Icon icon='chevron-up' />
360
+ <Icon icon='chevron-up' size="xs"/>
373
361
  </div>
374
362
  )}
375
363
  </div>
@@ -1,3 +1,5 @@
1
1
  The `returnAllSelected` or `return_all_selected` prop can be used when users want data on all checked nodes from the dropdown, irrespective of whether it is a parent or child node.
2
2
 
3
- __NOTE__ :This variant also does not automatically uncheck the parent when any of the child nodes are unchecked. `returnAllSelected` is set to false by default.
3
+ __NOTE__: This variant also does not automatically uncheck the parent when any of the child nodes are unchecked. `returnAllSelected` is set to false by default.
4
+
5
+ __NOTE__: For larger trees that may return many pill selections, you can optionally set `input_display: "none"`(for Rails) or `inputDisplay = "none"`(for React) to hide all pills within the input.
@@ -9,6 +9,11 @@ module Playbook
9
9
  default: []
10
10
  prop :return_all_selected, type: Playbook::Props::Boolean,
11
11
  default: false
12
+ prop :selected_ids, type: Playbook::Props::Array,
13
+ default: []
14
+ prop :input_display, type: Playbook::Props::Enum,
15
+ values: %w[pills none],
16
+ default: "pills"
12
17
 
13
18
  def classname
14
19
  generate_classname("pb_multi_level_select")
@@ -17,9 +22,11 @@ module Playbook
17
22
  def multi_level_select_options
18
23
  {
19
24
  id: id,
25
+ inputDisplay: input_display,
20
26
  name: name,
21
27
  treeData: tree_data,
22
28
  returnAllSelected: return_all_selected,
29
+ selectedIds: selected_ids,
23
30
  }
24
31
  end
25
32
  end
@@ -171,19 +171,17 @@ const PbReactPopover = (props: PbPopoverProps) => {
171
171
 
172
172
  switch (closeOnClick) {
173
173
  case "outside":
174
- if (!targetIsPopover && !targetIsReference) {
174
+ if (!targetIsPopover || targetIsReference) {
175
175
  shouldClosePopover(true);
176
176
  }
177
177
  break;
178
178
  case "inside":
179
- if (targetIsPopover) {
179
+ if (targetIsPopover || targetIsReference) {
180
180
  shouldClosePopover(true);
181
181
  }
182
182
  break;
183
183
  case "any":
184
- if (targetIsPopover || !targetIsPopover && !targetIsReference) {
185
- shouldClosePopover(true);
186
- }
184
+ shouldClosePopover(true);
187
185
  break;
188
186
  }
189
187
  },
@@ -49,16 +49,13 @@ export default class PbPopover extends PbEnhancedElement {
49
49
  checkCloseTooltip() {
50
50
  document.querySelector('body').addEventListener('click', ({ target } ) => {
51
51
  const isTooltipElement = (target as HTMLElement).closest(`#${this.tooltipId}`) !== null
52
- const isTriggerElement = (target as HTMLElement).closest(`#${this.triggerElementId}`) !== null
53
52
 
54
53
  switch (this.closeOnClick) {
55
54
  case 'any':
56
- if (isTooltipElement || !isTooltipElement && !isTriggerElement) {
57
- this.hideTooltip()
58
- }
55
+ this.hideTooltip()
59
56
  break
60
57
  case 'outside':
61
- if (!isTooltipElement && !isTriggerElement) {
58
+ if (!isTooltipElement) {
62
59
  this.hideTooltip()
63
60
  }
64
61
  break
@@ -30,19 +30,5 @@
30
30
  <td>Value 4</td>
31
31
  <td>Value 5</td>
32
32
  </tr>
33
- <tr>
34
- <td>Value 1</td>
35
- <td>Value 2</td>
36
- <td>Value 3</td>
37
- <td>Value 4</td>
38
- <td>Value 5</td>
39
- </tr>
40
- <tr>
41
- <td>Value 1</td>
42
- <td>Value 2</td>
43
- <td>Value 3</td>
44
- <td>Value 4</td>
45
- <td>Value 5</td>
46
- </tr>
47
33
  </tbody>
48
34
  <% end %>
@@ -0,0 +1 @@
1
+ Tighter spacing in first- and last-child cells of each row for data-heavy tables.
@@ -39,10 +39,22 @@
39
39
  thead tr th {
40
40
  padding-top: $cell-pad-sm;
41
41
  padding-bottom: $cell-pad-sm;
42
+ &:first-child {
43
+ padding-left: $cell-pad-sm;
44
+ }
45
+ &:last-child {
46
+ padding-right: $cell-pad-sm;
47
+ }
42
48
  }
43
49
  tbody tr td {
44
50
  padding-top: $cell-pad-sm;
45
51
  padding-bottom: $cell-pad-sm;
52
+ &:first-child {
53
+ padding-left: $cell-pad-sm;
54
+ }
55
+ &:last-child {
56
+ padding-right: $cell-pad-sm;
57
+ }
46
58
  }
47
59
  }
48
60
  }
@@ -2,6 +2,7 @@ import { omit } from 'lodash'
2
2
  import { camelToSnakeCase } from './text'
3
3
 
4
4
  import {
5
+ BitValues,
5
6
  Binary,
6
7
  Display,
7
8
  DisplaySizes,
@@ -48,7 +49,7 @@ type FlexDirection = {
48
49
  }
49
50
 
50
51
  type FlexGrow = {
51
- flexGrow?: 0 | 1
52
+ flexGrow?: Binary
52
53
  }
53
54
 
54
55
  type FlexShrink = {
@@ -316,15 +317,19 @@ const PROP_CATEGORIES: {[key:string]: (props: {[key: string]: any}) => string} =
316
317
  flexGrowProps: ({ flexGrow }: FlexGrow) => {
317
318
  if (typeof flexGrow == 'object') {
318
319
  return getResponsivePropClasses(flexGrow, 'flex_grow')
320
+ } else if (BitValues.includes(flexGrow)) {
321
+ return `flex_grow_${flexGrow}`
319
322
  } else {
320
- return flexGrow ? `flex_grow_${flexGrow}` : ''
323
+ return ''
321
324
  }
322
325
  },
323
326
  flexShrinkProps: ({ flexShrink }: FlexShrink) => {
324
327
  if (typeof flexShrink == 'object') {
325
328
  return getResponsivePropClasses(flexShrink, 'flex_shrink')
329
+ } else if (BitValues.includes(flexShrink)) {
330
+ return `flex_shrink_${flexShrink}`
326
331
  } else {
327
- return flexShrink ? `flex_shrink_${flexShrink}` : ''
332
+ return ''
328
333
  }
329
334
  },
330
335
  justifyContentProps: ({ justifyContent }: JustifyContent) => {
@@ -392,4 +397,4 @@ export const domSafeProps = (props: {[key: string]: string}): {[key: string]: st
392
397
  'dark',
393
398
  ]
394
399
  return omit(props, notSafeProps)
395
- }
400
+ }
@@ -12,7 +12,7 @@ test('Global Props: Returns ordinal suffixed class name', () => {
12
12
  render(
13
13
  <Body
14
14
  data={{ testid: testId }}
15
- flexGrow={`${x}`}
15
+ flexGrow={x}
16
16
  text="Hi"
17
17
  />
18
18
  )
@@ -12,7 +12,7 @@ test('Global Props: Returns ordinal suffixed class name', () => {
12
12
  render(
13
13
  <Body
14
14
  data={{ testid: testId }}
15
- flexShrink={`${x}`}
15
+ flexShrink={x}
16
16
  text="Hi"
17
17
  />
18
18
  )