playbook_ui 12.19.0 → 12.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +1 -2
  3. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +22 -7
  4. data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +32 -5
  5. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.scss +9 -4
  6. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.tsx +5 -3
  7. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +2 -1
  8. data/app/pb_kits/playbook/pb_typeahead/{_typeahead.jsx → _typeahead.tsx} +24 -12
  9. data/app/pb_kits/playbook/pb_typeahead/components/{ClearIndicator.jsx → ClearIndicator.tsx} +2 -4
  10. data/app/pb_kits/playbook/pb_typeahead/components/{Control.jsx → Control.tsx} +5 -7
  11. data/app/pb_kits/playbook/pb_typeahead/components/{IndicatorsContainer.jsx → IndicatorsContainer.tsx} +2 -4
  12. data/app/pb_kits/playbook/pb_typeahead/components/{MenuList.jsx → MenuList.tsx} +0 -2
  13. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +66 -0
  14. data/app/pb_kits/playbook/pb_typeahead/components/Option.tsx +37 -0
  15. data/app/pb_kits/playbook/pb_typeahead/components/{Placeholder.jsx → Placeholder.tsx} +7 -9
  16. data/app/pb_kits/playbook/pb_typeahead/components/{ValueContainer.jsx → ValueContainer.tsx} +3 -5
  17. data/app/pb_kits/playbook/pb_typeahead/{index.js → index.ts} +37 -29
  18. data/app/pb_kits/playbook/pb_typeahead/types.d.ts +2 -0
  19. data/app/pb_kits/playbook/pb_user/_user.tsx +1 -1
  20. data/app/pb_kits/playbook/utilities/_positioning.scss +14 -0
  21. data/app/pb_kits/playbook/utilities/globalProps.ts +16 -4
  22. data/lib/playbook/version.rb +2 -2
  23. data/lib/playbook/z_index.rb +20 -7
  24. metadata +13 -12
  25. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.jsx +0 -62
  26. data/app/pb_kits/playbook/pb_typeahead/components/Option.jsx +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f60bb863c6a7be595fe8ffcaa866a7796a0bb896732cf7ba5990d40444e6405
4
- data.tar.gz: a3e06332bf074ce75e69c35184fd624b26ee9bfd02efcfad057dbafbcac3c608
3
+ metadata.gz: 86c4aefb2ca62f0357facbacd990e8ef9283fe061b307b2b3a48d9a44aae93bd
4
+ data.tar.gz: d46b8bcadd416bed1be375a1a60789b9e82ed3998a7e94d511f183a887e13654
5
5
  SHA512:
6
- metadata.gz: c30ebfe71f1649440d65fda7871d6c6b4d11a0ced08299f38b5de90bd9f0c3108e3179e54fcbe3a064ef0b0411a11eb76382fcb9e464b2cc5c88e7c57224b33d
7
- data.tar.gz: dda14920f8aa81dc398a665fee7b51d4bbedf537669f297fe76b3f04df0b813b47229cff6e809571bf62bbaa00909e9956b6e77d1895e338a956b4d3bf6d947d
6
+ metadata.gz: 9f016eb2b9946595c6bc70b9b48bd7faffe5249084040bc5a0046fa4b9c08fb006a245c5b570a296bc130795b1e510701a0e765c0018ca66dd322bf56619ea96
7
+ data.tar.gz: e08f975d11599e129cf94ce4f4c91f965708fe984565e46538f8dd254577bee99e59cc26d2d8c51948bbcc3488ccf61d7be997ae9ffd3a60ac23e9ea0a616727
@@ -36,10 +36,9 @@
36
36
  vertical-align: top;
37
37
  width: 0.6em;
38
38
  top: 10px;
39
- transform: rotate(135deg);
40
39
  font-size: 0.5em;
41
40
 
42
- transform: rotate(-45deg);
41
+ transform: rotate(45deg);
43
42
  top: 12px;
44
43
  }
45
44
 
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useMemo } from "react";
2
2
  import classnames from "classnames";
3
3
  import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props";
4
4
  import { globalProps } from "../utilities/globalProps";
5
- import { findItemById, checkIt, unCheckIt } from "./helper_functions";
5
+ import { findItemById, checkIt, unCheckIt, getParentAndAncestorsIds } from "./helper_functions";
6
6
  import MultiSelectHelper from "./_multi_select_helper";
7
7
 
8
8
  type MultiLevelSelectProps = {
@@ -42,17 +42,31 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
42
42
  const updatedData = formattedData.map((item: any) => {
43
43
  if (item.id === currentNode._id) {
44
44
  if (currentNode.checked) {
45
- checkIt(item, selectedItems, setSelectedItems);
45
+ checkIt(item, selectedItems, setSelectedItems, false);
46
46
  } else {
47
- unCheckIt(item, selectedItems, setSelectedItems);
47
+ unCheckIt(item, selectedItems, setSelectedItems, false);
48
48
  }
49
49
  } else if (item.children) {
50
50
  const foundItem = findItemById(item.children, currentNode._id);
51
51
  if (foundItem) {
52
52
  if (currentNode.checked) {
53
- checkIt(foundItem, selectedItems, setSelectedItems);
53
+ checkIt(foundItem, selectedItems, setSelectedItems, false);
54
+ if (currentNode._parent) {
55
+ const parents = getParentAndAncestorsIds(currentNode._parent, formattedData)
56
+ parents.forEach((item:string) => {
57
+ const ancestor = findItemById(formattedData,item)
58
+ ancestor.expanded = true
59
+ });
60
+ }
54
61
  } else {
55
- unCheckIt(foundItem, selectedItems, setSelectedItems);
62
+ unCheckIt(foundItem, selectedItems, setSelectedItems, false);
63
+ if (currentNode._parent) {
64
+ const parents = getParentAndAncestorsIds(currentNode._parent, formattedData)
65
+ parents.forEach((item:string) => {
66
+ const ancestor = findItemById(formattedData,item)
67
+ ancestor.expanded = true
68
+ });
69
+ }
56
70
  }
57
71
  }
58
72
  }
@@ -92,17 +106,18 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
92
106
  treeData={formattedData}
93
107
  onChange={(
94
108
  // @ts-ignore
95
- selectedNodes: { [key: string]: any }[],
109
+ selectedNodes: { [key: string]: any }[],
96
110
  currentNode: { [key: string]: any }[]
97
111
  ) => {
98
112
  setCheckedData(currentNode);
99
113
  onSelect(currentNode);
114
+
100
115
  }}
101
116
  id={id}
102
117
  {...props}
103
118
  />
104
119
  );
105
- }, [formattedData]);
120
+ }, [formattedData])
106
121
 
107
122
  return (
108
123
  <div {...ariaProps} {...dataProps} className={classes} id={id}>
@@ -19,19 +19,20 @@ export const findItemById = (
19
19
  export const checkIt = (
20
20
  foundItem: { [key: string]: any },
21
21
  selectedItems: any[],
22
- setSelectedItems: Function
22
+ setSelectedItems: Function,
23
+ expand: boolean
23
24
  ) => {
24
25
  if (!foundItem) {
25
26
  return;
26
27
  }
27
28
 
28
29
  foundItem.checked = true;
29
- foundItem.expanded = true;
30
+ foundItem.expanded = expand;
30
31
  selectedItems.push(foundItem);
31
32
 
32
33
  if (foundItem.children) {
33
34
  foundItem.children.map((x: any) => {
34
- checkIt(x, selectedItems, setSelectedItems);
35
+ checkIt(x, selectedItems, setSelectedItems, expand);
35
36
  });
36
37
  }
37
38
 
@@ -41,20 +42,46 @@ export const checkIt = (
41
42
  export const unCheckIt = (
42
43
  foundItem: { [key: string]: any },
43
44
  selectedItems: any,
44
- setSelectedItems: any
45
+ setSelectedItems: any,
46
+ expand: boolean
45
47
  ) => {
46
48
  if (!foundItem) {
47
49
  return;
48
50
  }
49
51
 
50
52
  foundItem.checked = false;
53
+ foundItem.expanded = false;
51
54
  const newSelectedItems = selectedItems.filter(
52
55
  (item: any) => item.id !== foundItem.id
53
56
  );
54
57
  if (foundItem.children) {
55
58
  foundItem.children.map((x: any) => {
56
- unCheckIt(x, selectedItems, setSelectedItems);
59
+ unCheckIt(x, selectedItems, setSelectedItems, expand);
57
60
  });
58
61
  }
59
62
  setSelectedItems([...newSelectedItems]);
60
63
  };
64
+
65
+
66
+ export const getParentAndAncestorsIds = (itemId:string, items:{ [key: string]: string; }[], ancestors:string[] = []):any => {
67
+ for (let i = 0; i < items.length; i++) {
68
+ const item:any = items[i];
69
+ if (item.id === itemId) {
70
+ // item found in current level of items array
71
+ return [...ancestors, item.id];
72
+ }
73
+ if (item.children && item.children.length > 0) {
74
+ // recursively search through children
75
+ const foundAncestors = getParentAndAncestorsIds(
76
+ itemId,
77
+ item.children,
78
+ [...ancestors, item.id]
79
+ );
80
+ if (foundAncestors) {
81
+ return foundAncestors;
82
+ }
83
+ }
84
+ }
85
+ // item not found in this level of items array or its children
86
+ return null;
87
+ }
@@ -81,10 +81,11 @@ $pb_selectable_card_border: 2px;
81
81
  }
82
82
 
83
83
  .separator {
84
- width: 2px;
85
- margin-right: 0px;
86
84
  background: $royal;
87
85
  }
86
+ .psuedo_separator {
87
+ background-color: $royal;
88
+ }
88
89
  }
89
90
  }
90
91
  }
@@ -125,13 +126,17 @@ $pb_selectable_card_border: 2px;
125
126
 
126
127
  .separator {
127
128
  align-self: stretch;
128
- width: 1px;
129
- margin-right: 1px;
129
+ padding-right: 1px;
130
130
  margin-top: -1px;
131
131
  margin-bottom: -1px;
132
132
  background: $border_light;
133
133
  }
134
134
 
135
+ .psuedo_separator {
136
+ align-self: stretch;
137
+ padding-right: 1px;
138
+ }
139
+
135
140
  &.error {
136
141
  > label {
137
142
  border-color: $error;
@@ -13,9 +13,9 @@ import {
13
13
 
14
14
  import Icon from '../pb_icon/_icon'
15
15
  import Checkbox from '../pb_checkbox/_checkbox'
16
- import Card from '../pb_card/_card'
17
16
  import Flex from '../pb_flex/_flex'
18
17
  import Radio from '../pb_radio/_radio'
18
+ import Card from '../pb_card/_card'
19
19
 
20
20
  type SelectableCardProps = {
21
21
  aria?: { [key: string]: string },
@@ -149,13 +149,15 @@ const SelectableCard = (props: SelectableCardProps) => {
149
149
  </Input>
150
150
  </Flex>
151
151
  <div className="separator" />
152
- <Card.Body
152
+ <div className="psuedo_separator"/>
153
+ <Card
154
+ borderNone
153
155
  dark={dark}
154
156
  padding="sm"
155
157
  status={error ? 'negative' : null}
156
158
  >
157
159
  {text ||props.children}
158
- </Card.Body>
160
+ </Card>
159
161
  </Flex>
160
162
  :
161
163
  text || props.children
@@ -24,7 +24,8 @@
24
24
  <% end %>
25
25
  <% end %>
26
26
  <div class="separator"></div>
27
- <%= pb_rails("card/card_body", props: { padding: "sm", status: object.status }) do %>
27
+ <div class="psuedo_separator"></div>
28
+ <%= pb_rails("card", props: { padding: "sm", status: object.status, border_none: true }) do %>
28
29
  <% if content.nil? %>
29
30
  <%= pb_rails("body", props: { text: object.text }) %>
30
31
  <% else %>
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import Select from 'react-select'
5
3
  import AsyncSelect from 'react-select/async'
@@ -19,6 +17,7 @@ import Placeholder from './components/Placeholder'
19
17
  import ValueContainer from './components/ValueContainer'
20
18
 
21
19
  import { noop, buildDataProps } from '../utilities/props'
20
+ import { Noop } from '../types'
22
21
 
23
22
  /**
24
23
  * @typedef {object} Props
@@ -33,16 +32,28 @@ type TypeaheadProps = {
33
32
  components?: object,
34
33
  createable?: boolean,
35
34
  dark?: boolean,
36
- data?: object,
35
+ data?: { [key: string]: string },
37
36
  error?: string,
38
37
  id?: string,
39
38
  label?: string,
40
- loadOptions?: string,
39
+ loadOptions?: string | Noop,
41
40
  getOptionLabel?: string | (() => any),
42
41
  getOptionValue?: string | (() => any),
43
42
  name?: string,
44
43
  }
45
44
 
45
+ export type SelectValueType = {
46
+ label: string,
47
+ value: string,
48
+ imageUrl?: string,
49
+ }
50
+
51
+ type TagOnChangeValues = {
52
+ action?: string,
53
+ option?: SelectValueType,
54
+ removedValue?: string,
55
+ }
56
+
46
57
  /**
47
58
  * @constant {React.ReactComponent} Typeahead
48
59
  * @param {TypeaheadProps} props - props as described at https://react-select.com/props
@@ -67,7 +78,7 @@ const Typeahead = ({
67
78
  Control,
68
79
  ClearIndicator,
69
80
  IndicatorsContainer,
70
- IndicatorSeparator: null,
81
+ IndicatorSeparator: null as null,
71
82
  MenuList,
72
83
  MultiValue,
73
84
  Option,
@@ -85,8 +96,9 @@ const Typeahead = ({
85
96
  isSearchable: true,
86
97
  name,
87
98
  multiKit: '',
88
- onCreateOption: null,
99
+ onCreateOption: null as null,
89
100
  plusIcon: false,
101
+ onMultiValueClick: (_option: SelectValueType) => { },
90
102
  ...props,
91
103
  }
92
104
 
@@ -96,7 +108,7 @@ const Typeahead = ({
96
108
  : (async ? AsyncSelect : Select)
97
109
  )
98
110
 
99
- const handleOnChange = (_data, { action, option, removedValue }) => {
111
+ const handleOnChange = (_data: SelectValueType, { action, option, removedValue }: TagOnChangeValues) => {
100
112
  if (action === 'select-option') {
101
113
  if (selectProps.onMultiValueClick) selectProps.onMultiValueClick(option)
102
114
  const multiValueClearEvent = new CustomEvent(`pb-typeahead-kit-${selectProps.id}-result-option-select`, { detail: option ? option : _data })
@@ -123,13 +135,13 @@ const Typeahead = ({
123
135
 
124
136
  return (
125
137
  <div {...dataProps}
126
- className={classnames(classes, inlineClass)}
138
+ className={classnames(classes, inlineClass)}
127
139
  >
128
140
  <Tag
129
- classNamePrefix="typeahead-kit-select"
130
- error={error}
131
- onChange={handleOnChange}
132
- {...selectProps}
141
+ classNamePrefix="typeahead-kit-select"
142
+ error={error}
143
+ onChange={handleOnChange}
144
+ {...selectProps}
133
145
  />
134
146
  </div>
135
147
  )
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React, { useEffect } from 'react'
4
2
  import { components } from 'react-select'
5
3
 
@@ -11,8 +9,8 @@ const ClearContainer = (props: any) => {
11
9
 
12
10
  return (
13
11
  <components.ClearIndicator
14
- className="clear_indicator"
15
- {...props}
12
+ className="clear_indicator"
13
+ {...props}
16
14
  />
17
15
  )
18
16
  }
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import { components } from 'react-select'
5
3
 
@@ -13,14 +11,14 @@ type Props = {
13
11
  const TypeaheadControl = (props: Props) => (
14
12
  <div className="pb_typeahead_wrapper">
15
13
  <TextInput
16
- dark={props.selectProps.dark}
17
- error={props.selectProps.error}
18
- label={props.selectProps.label}
14
+ dark={props.selectProps.dark}
15
+ error={props.selectProps.error}
16
+ label={props.selectProps.label}
19
17
  >
20
18
  <Flex>
21
19
  <components.Control
22
- className="text_input"
23
- {...props}
20
+ className="text_input"
21
+ {...props}
24
22
  />
25
23
  </Flex>
26
24
  </TextInput>
@@ -1,12 +1,10 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import { components } from 'react-select'
5
3
 
6
4
  const IndicatorsContainer = (props: any) => (
7
5
  <components.IndicatorsContainer
8
- className="text_input_indicators"
9
- {...props}
6
+ className="text_input_indicators"
7
+ {...props}
10
8
  />
11
9
  )
12
10
 
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import { components } from 'react-select'
5
3
 
@@ -0,0 +1,66 @@
1
+ import React from 'react'
2
+ import { components } from 'react-select'
3
+
4
+ import Badge from '../../pb_badge/_badge'
5
+ import FormPill from '../../pb_form_pill/_form_pill'
6
+ import { SelectValueType } from '../_typeahead'
7
+
8
+ type Props = {
9
+ data: SelectValueType,
10
+ multiValueTemplate: any,
11
+ removeProps: any,
12
+ selectProps: any,
13
+ }
14
+
15
+ const MultiValue = (props: Props) => {
16
+ const { removeProps } = props
17
+ const { imageUrl, label } = props.data
18
+ const { multiKit } = props.selectProps
19
+
20
+ const formPillProps = {
21
+ marginRight: 'xs',
22
+ name: label,
23
+ avatarUrl: '',
24
+ }
25
+
26
+ if (typeof imageUrl === 'string') formPillProps.avatarUrl = imageUrl
27
+
28
+ return (
29
+ <components.MultiValueContainer
30
+ className="text_input_multivalue_container"
31
+ {...props}
32
+ >
33
+ {multiKit === 'badge' &&
34
+ <Badge
35
+ closeProps={removeProps}
36
+ removeIcon
37
+ text={label}
38
+ variant="primary"
39
+ />
40
+ }
41
+
42
+ {multiKit !== 'badge' && imageUrl &&
43
+ <FormPill
44
+ avatarUrl={imageUrl}
45
+ closeProps={removeProps}
46
+ marginRight="xs"
47
+ name={label}
48
+ size={multiKit === 'smallPill' ? 'small' : ''}
49
+ text=''
50
+ />
51
+ }
52
+
53
+ {multiKit !== 'badge' && !imageUrl &&
54
+ <FormPill
55
+ closeProps={removeProps}
56
+ marginRight="xs"
57
+ name=''
58
+ size={multiKit === 'smallPill' ? 'small' : ''}
59
+ text={label}
60
+ />
61
+ }
62
+ </components.MultiValueContainer>
63
+ )
64
+ }
65
+
66
+ export default MultiValue
@@ -0,0 +1,37 @@
1
+ import React from 'react'
2
+ import { components } from 'react-select'
3
+
4
+ import User from '../../pb_user/_user'
5
+
6
+ const Option = (props: any) => {
7
+ const {
8
+ imageUrl,
9
+ } = props.data
10
+ const { valueComponent } = props.selectProps
11
+
12
+ return (
13
+ <components.Option {...props}>
14
+ <>
15
+ {!valueComponent && imageUrl &&
16
+ <User
17
+ align="left"
18
+ avatarUrl={imageUrl}
19
+ dark={props.selectProps.dark}
20
+ name={props.label}
21
+ orientation="horizontal"
22
+ />
23
+ }
24
+
25
+ {valueComponent &&
26
+ valueComponent(props.data)
27
+ }
28
+
29
+ {!valueComponent && !imageUrl &&
30
+ props.label
31
+ }
32
+ </>
33
+ </components.Option>
34
+ )
35
+ }
36
+
37
+ export default Option
@@ -1,5 +1,3 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import { components } from 'react-select'
5
3
 
@@ -9,18 +7,18 @@ import Icon from '../../pb_icon/_icon'
9
7
  const Placeholder = (props: any) => (
10
8
  <>
11
9
  <Flex
12
- align="center"
13
- className="placeholder"
10
+ align="center"
11
+ className="placeholder"
14
12
  >
15
13
  <components.IndicatorsContainer
16
- {...props}
14
+ {...props}
17
15
  />
18
- <If condition={props.selectProps.plusIcon}>
16
+ {props.selectProps.plusIcon &&
19
17
  <Icon
20
- className="typeahead-plus-icon"
21
- icon="plus"
18
+ className="typeahead-plus-icon"
19
+ icon="plus"
22
20
  />
23
- </If>
21
+ }
24
22
  </Flex>
25
23
  </>
26
24
  )
@@ -1,12 +1,10 @@
1
- /* @flow */
2
-
3
1
  import React from 'react'
4
2
  import { components } from 'react-select'
5
3
 
6
- const ValueContainer = (props: Props) => (
4
+ const ValueContainer = (props: any) => (
7
5
  <components.ValueContainer
8
- className="text_input_value_container"
9
- {...props}
6
+ className="text_input_value_container"
7
+ {...props}
10
8
  />
11
9
  )
12
10
 
@@ -2,18 +2,26 @@ import PbEnhancedElement from '../pb_enhanced_element'
2
2
  import { debounce } from 'lodash'
3
3
 
4
4
  export default class PbTypeahead extends PbEnhancedElement {
5
+ _searchInput: HTMLInputElement
6
+ _resultsElement: HTMLElement
7
+ _debouncedSearch: Function
8
+ _resultsLoadingIndicator: HTMLElement
9
+ _resultOptionTemplate: HTMLElement
10
+ _resultsOptionCache: Map<string, Array<DocumentFragment>>
11
+ _searchContext: string
12
+
5
13
  static get selector() {
6
14
  return '[data-pb-typeahead-kit]'
7
15
  }
8
16
 
9
17
  connect() {
10
- this.element.addEventListener('keydown', (event) => this.handleKeydown(event))
18
+ this.element.addEventListener('keydown', (event: KeyboardEvent) => this.handleKeydown(event))
11
19
  this.searchInput.addEventListener('focus', () => this.debouncedSearch())
12
20
  this.searchInput.addEventListener('input', () => this.debouncedSearch())
13
- this.resultsElement.addEventListener('click', (event) => this.optionSelected(event))
21
+ this.resultsElement.addEventListener('click', (event: MouseEvent) => this.optionSelected(event))
14
22
  }
15
23
 
16
- handleKeydown(event) {
24
+ handleKeydown(event: KeyboardEvent) {
17
25
  if (event.key === 'ArrowUp') {
18
26
  event.preventDefault()
19
27
  this.focusPreviousOption()
@@ -24,7 +32,7 @@ export default class PbTypeahead extends PbEnhancedElement {
24
32
  }
25
33
 
26
34
  search() {
27
- if (this.searchTerm.length < this.searchTermMinimumLength) return this.clearResults()
35
+ if (this.searchTerm.length < parseInt(this.searchTermMinimumLength)) return this.clearResults()
28
36
 
29
37
  this.toggleResultsLoadingIndicator(true)
30
38
  this.showResults()
@@ -34,17 +42,17 @@ export default class PbTypeahead extends PbEnhancedElement {
34
42
  const search = {
35
43
  searchingFor: searchTerm,
36
44
  searchingContext: searchContext,
37
- setResults: (results) => {
45
+ setResults: (results: Array<DocumentFragment>) => {
38
46
  this.resultsCacheUpdate(searchTerm, searchContext, results)
39
47
  },
40
48
  }
41
49
  this.element.dispatchEvent(new CustomEvent('pb-typeahead-kit-search', { bubbles: true, detail: search }))
42
50
  }
43
51
 
44
- resultsCacheUpdate(searchTerm, searchContext, results) {
52
+ resultsCacheUpdate(searchTerm: string, searchContext: string, results: Array<DocumentFragment>) {
45
53
  const searchTermAndContext = this.cacheKeyFor(searchTerm, searchContext)
46
54
  if (this.resultsOptionCache.has(searchTermAndContext)) this.resultsOptionCache.delete(searchTermAndContext)
47
- if (this.resultsOptionCache.size > 32) this.resultsOptionCache.delete(this.resultsOptionCache.keys[0])
55
+ if (this.resultsOptionCache.size > 32) this.resultsOptionCache.delete(this.resultsOptionCache.keys().next().value)
48
56
 
49
57
  this.resultsOptionCache.set(searchTermAndContext, results)
50
58
  this.showResults()
@@ -57,7 +65,7 @@ export default class PbTypeahead extends PbEnhancedElement {
57
65
  get debouncedSearch() {
58
66
  return this._debouncedSearch = (
59
67
  this._debouncedSearch ||
60
- debounce(this.search, this.searchDebounceTimeout).bind(this)
68
+ debounce(this.search, parseInt(this.searchDebounceTimeout)).bind(this)
61
69
  )
62
70
  }
63
71
 
@@ -70,12 +78,12 @@ export default class PbTypeahead extends PbEnhancedElement {
70
78
  this.resultsElement.appendChild(this.newResultOption(result.cloneNode(true)))
71
79
  }
72
80
  for (const result of this.resultsElement.querySelectorAll('[data-result-option-item]')) {
73
- result.addEventListener('mousedown', (event) => this.optionSelected(event))
81
+ result.addEventListener('mousedown', (event: MouseEvent) => this.optionSelected(event))
74
82
  }
75
83
  }
76
84
 
77
- optionSelected(event) {
78
- const resultOption = event.target.closest('[data-result-option-item]')
85
+ optionSelected(event: MouseEvent) {
86
+ const resultOption = (event.target as Element).closest('[data-result-option-item]')
79
87
  if (!resultOption) return
80
88
 
81
89
  this.resultsCacheClear()
@@ -89,8 +97,8 @@ export default class PbTypeahead extends PbEnhancedElement {
89
97
  this.resultsElement.innerHTML = ''
90
98
  }
91
99
 
92
- newResultOption(content) {
93
- const resultOption = this.resultOptionTemplate.content.cloneNode(true)
100
+ newResultOption(content: DocumentFragment) {
101
+ const resultOption = (this.resultOptionTemplate as HTMLTemplateElement).content.cloneNode(true) as Element
94
102
  resultOption.querySelector('slot[name="content"]').replaceWith(content)
95
103
  return resultOption
96
104
  }
@@ -100,9 +108,9 @@ export default class PbTypeahead extends PbEnhancedElement {
100
108
  const previousIndex = currentIndex - 1
101
109
  const previousOptionItem = (
102
110
  this.resultOptionItems[previousIndex] ||
103
- this.resultOptionItems[this.resultOptionItems.length - 1]
104
- )
105
- previousOptionItem.focus()
111
+ this.resultOptionItems[this.resultOptionItems.length - 1]
112
+ );
113
+ (previousOptionItem as HTMLElement).focus()
106
114
  }
107
115
 
108
116
  focusNextOption() {
@@ -110,9 +118,9 @@ export default class PbTypeahead extends PbEnhancedElement {
110
118
  const nextIndex = currentIndex + 1
111
119
  const nextOptionItem = (
112
120
  this.resultOptionItems[nextIndex] ||
113
- this.resultOptionItems[0]
114
- )
115
- nextOptionItem.focus()
121
+ this.resultOptionItems[0]
122
+ );
123
+ (nextOptionItem as HTMLElement).focus()
116
124
  }
117
125
 
118
126
  get resultOptionItems() {
@@ -134,11 +142,11 @@ export default class PbTypeahead extends PbEnhancedElement {
134
142
  get searchContext() {
135
143
  if (this._searchContext) return this._searchContext
136
144
 
137
- const selector = this.element.dataset.searchContextValueSelector
138
- if (selector) return (
145
+ const selector = (this.element as HTMLElement).dataset.searchContextValueSelector
146
+ if (selector) return ((
139
147
  this.element.parentNode.querySelector(selector) ||
140
- this.element.closest(selector)
141
- ).value
148
+ this.element.closest(selector)
149
+ ) as HTMLInputElement).value
142
150
 
143
151
  return null
144
152
  }
@@ -151,7 +159,7 @@ export default class PbTypeahead extends PbEnhancedElement {
151
159
  return this.cacheKeyFor(this.searchTerm, this.searchContext)
152
160
  }
153
161
 
154
- cacheKeyFor(searchTerm, searchContext) {
162
+ cacheKeyFor(searchTerm: string, searchContext: string) {
155
163
  return [searchTerm, JSON.stringify(searchContext)].join()
156
164
  }
157
165
 
@@ -160,11 +168,11 @@ export default class PbTypeahead extends PbEnhancedElement {
160
168
  }
161
169
 
162
170
  get searchTermMinimumLength() {
163
- return this.element.dataset.pbTypeaheadKitSearchTermMinimumLength
171
+ return (this.element as HTMLElement).dataset.pbTypeaheadKitSearchTermMinimumLength
164
172
  }
165
173
 
166
174
  get searchDebounceTimeout() {
167
- return this.element.dataset.pbTypeaheadKitSearchDebounceTimeout
175
+ return (this.element as HTMLElement).dataset.pbTypeaheadKitSearchDebounceTimeout
168
176
  }
169
177
 
170
178
  get resultsElement() {
@@ -192,9 +200,9 @@ export default class PbTypeahead extends PbEnhancedElement {
192
200
  )
193
201
  }
194
202
 
195
- toggleResultsLoadingIndicator(visible) {
196
- var visibilityProperty = 0
197
- if (visible) visibilityProperty = 1
203
+ toggleResultsLoadingIndicator(visible: boolean) {
204
+ var visibilityProperty = '0'
205
+ if (visible) visibilityProperty = '1'
198
206
  this.resultsLoadingIndicator.style.opacity = visibilityProperty
199
207
  }
200
208
  }
@@ -0,0 +1,2 @@
1
+ declare module 'react-select'
2
+ declare module 'react-select/*'
@@ -18,7 +18,7 @@ type UserProps = {
18
18
  data?: {[key: string]: string},
19
19
  id?: string,
20
20
  name?: string,
21
- orientation?: "horiztonal" | "vertical",
21
+ orientation?: "horizontal" | "vertical",
22
22
  size?: "sm" | "md" | "lg",
23
23
  subtitle?: string | Array<Node> | Node,
24
24
  territory?: string,
@@ -48,3 +48,17 @@
48
48
  .z_index_10 {
49
49
  z-index: 1000;
50
50
  }
51
+
52
+ $zIndex_values: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
53
+
54
+ @each $size, $size_value in $breakpoints_grid {
55
+ @each $zIndex_value in $zIndex_values {
56
+ $min_size: map-get($size_value, "min");
57
+ $max_size: map-get($size_value, "max");
58
+ .z_index_#{$size}_#{$zIndex_value} {
59
+ @include break_on($min_size, $max_size) {
60
+ z-index: #{$zIndex_value * 100} !important;
61
+ }
62
+ }
63
+ }
64
+ }
@@ -113,9 +113,11 @@ type Shadow = {
113
113
 
114
114
  type Space = "spaceBetween" | "spaceAround" | "spaceEvenly"
115
115
 
116
+ type ZIndexType = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
117
+ type ZIndexResponsiveType = {[key: string]: ZIndexType}
116
118
  type ZIndex = {
117
- zIndex?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10,
118
- }
119
+ zIndex?: ZIndexType,
120
+ } | ZIndexResponsiveType
119
121
 
120
122
  // keep this as the last type definition
121
123
  export type GlobalProps = AlignContent & AlignItems & AlignSelf &
@@ -178,9 +180,19 @@ const PROP_CATEGORIES: {[key:string]: (props: {[key: string]: any}) => string} =
178
180
  css += maxWidth ? `max_width_${maxWidth } ` : ''
179
181
  return css
180
182
  },
181
- zIndexProps: ({ zIndex }: ZIndex) => {
183
+ zIndexProps: (zIndex: ZIndex) => {
182
184
  let css = ''
183
- css += zIndex ? `z_index_${zIndex } ` : ''
185
+ Object.entries(zIndex).forEach((zIndexEntry) => {
186
+ if (zIndexEntry[0] == "zIndex") {
187
+ if (typeof zIndexEntry[1] == "number") {
188
+ css += `z_index_${zIndexEntry[1]} `
189
+ } else if (typeof zIndexEntry[1] == "object") {
190
+ Object.entries(zIndexEntry[1]).forEach((zIndexObj) => {
191
+ css += `z_index_${zIndexObj[0]}_${zIndexObj[1]} `
192
+ })
193
+ }
194
+ }
195
+ })
184
196
  return css
185
197
  },
186
198
  shadowProps: ({ shadow }: Shadow) => {
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playbook
4
- PREVIOUS_VERSION = "12.18.0"
5
- VERSION = "12.19.0"
4
+ PREVIOUS_VERSION = "12.19.0"
5
+ VERSION = "12.20.0"
6
6
  end
@@ -16,16 +16,29 @@ module Playbook
16
16
  }
17
17
  end
18
18
 
19
- private
19
+ def screen_size_values
20
+ %w[xs sm md lg xl]
21
+ end
20
22
 
21
23
  def z_index_props
22
- selected_index_props = z_index_options.keys.select { |sk| try(sk) }
23
- return nil unless selected_index_props.present?
24
+ selected_props = z_index_options.keys.select { |sk| try(sk) }
25
+ return nil unless selected_props.present?
26
+
27
+ responsive = selected_props.present? && try(:z_index).is_a?(::Hash)
28
+ css = ""
29
+ if responsive
30
+ z_index_value = send(:z_index)
31
+ z_index_value.each do |key, value|
32
+ css += "z_index_#{key}_#{value} " if screen_size_values.include?(key.to_s) && z_index_values.include?(value.to_s)
33
+ end
34
+ else
35
+ selected_props.each do |k|
36
+ z_index_value = send(k)
37
+ css += "z_index_#{z_index_value} " if z_index_values.include? z_index_value
38
+ end
39
+ end
24
40
 
25
- selected_index_props.map do |k|
26
- index_value = send(k)
27
- "z_index_#{index_value}" if z_index_values.include? index_value
28
- end.compact.join(" ")
41
+ css unless css.blank?
29
42
  end
30
43
  end
31
44
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playbook_ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 12.19.0
4
+ version: 12.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Power UX
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-05-09 00:00:00.000000000 Z
12
+ date: 2023-05-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -2248,17 +2248,17 @@ files:
2248
2248
  - app/pb_kits/playbook/pb_treemap_chart/docs/index.js
2249
2249
  - app/pb_kits/playbook/pb_treemap_chart/treemap_chart.html.erb
2250
2250
  - app/pb_kits/playbook/pb_treemap_chart/treemap_chart.rb
2251
- - app/pb_kits/playbook/pb_typeahead/_typeahead.jsx
2252
2251
  - app/pb_kits/playbook/pb_typeahead/_typeahead.scss
2253
2252
  - app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx
2254
- - app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.jsx
2255
- - app/pb_kits/playbook/pb_typeahead/components/Control.jsx
2256
- - app/pb_kits/playbook/pb_typeahead/components/IndicatorsContainer.jsx
2257
- - app/pb_kits/playbook/pb_typeahead/components/MenuList.jsx
2258
- - app/pb_kits/playbook/pb_typeahead/components/MultiValue.jsx
2259
- - app/pb_kits/playbook/pb_typeahead/components/Option.jsx
2260
- - app/pb_kits/playbook/pb_typeahead/components/Placeholder.jsx
2261
- - app/pb_kits/playbook/pb_typeahead/components/ValueContainer.jsx
2253
+ - app/pb_kits/playbook/pb_typeahead/_typeahead.tsx
2254
+ - app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.tsx
2255
+ - app/pb_kits/playbook/pb_typeahead/components/Control.tsx
2256
+ - app/pb_kits/playbook/pb_typeahead/components/IndicatorsContainer.tsx
2257
+ - app/pb_kits/playbook/pb_typeahead/components/MenuList.tsx
2258
+ - app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx
2259
+ - app/pb_kits/playbook/pb_typeahead/components/Option.tsx
2260
+ - app/pb_kits/playbook/pb_typeahead/components/Placeholder.tsx
2261
+ - app/pb_kits/playbook/pb_typeahead/components/ValueContainer.tsx
2262
2262
  - app/pb_kits/playbook/pb_typeahead/docs/_description.md
2263
2263
  - app/pb_kits/playbook/pb_typeahead/docs/_footer.md
2264
2264
  - app/pb_kits/playbook/pb_typeahead/docs/_typeahead_async_createable.jsx
@@ -2289,9 +2289,10 @@ files:
2289
2289
  - app/pb_kits/playbook/pb_typeahead/docs/_typeahead_without_pills.md
2290
2290
  - app/pb_kits/playbook/pb_typeahead/docs/example.yml
2291
2291
  - app/pb_kits/playbook/pb_typeahead/docs/index.js
2292
- - app/pb_kits/playbook/pb_typeahead/index.js
2292
+ - app/pb_kits/playbook/pb_typeahead/index.ts
2293
2293
  - app/pb_kits/playbook/pb_typeahead/typeahead.html.erb
2294
2294
  - app/pb_kits/playbook/pb_typeahead/typeahead.rb
2295
+ - app/pb_kits/playbook/pb_typeahead/types.d.ts
2295
2296
  - app/pb_kits/playbook/pb_user/_user.scss
2296
2297
  - app/pb_kits/playbook/pb_user/_user.tsx
2297
2298
  - app/pb_kits/playbook/pb_user/docs/_description.md
@@ -1,62 +0,0 @@
1
- /* @flow */
2
-
3
- import React from 'react'
4
- import { components } from 'react-select'
5
-
6
- import Badge from '../../pb_badge/_badge'
7
- import FormPill from '../../pb_form_pill/_form_pill'
8
-
9
- type Props = {
10
- data: object,
11
- multiValueTemplate: any,
12
- removeProps: any,
13
- selectProps: any,
14
- }
15
-
16
- const MultiValue = (props: Props) => {
17
- const { removeProps } = props
18
- const { imageUrl, label } = props.data
19
- const { multiKit } = props.selectProps
20
-
21
- const formPillProps = {
22
- marginRight: 'xs',
23
- name: label,
24
- }
25
-
26
- if (typeof imageUrl === 'string') formPillProps.avatarUrl = imageUrl
27
-
28
- return (
29
- <components.MultiValueContainer
30
- className="text_input_multivalue_container"
31
- {...props}
32
- >
33
- <If condition={multiKit === 'badge'}>
34
- <Badge
35
- closeProps={removeProps}
36
- removeIcon
37
- text={label}
38
- variant="primary"
39
- />
40
- <Else />
41
- <If condition={imageUrl}>
42
- <FormPill
43
- avatarUrl={imageUrl}
44
- closeProps={removeProps}
45
- marginRight="xs"
46
- name={label}
47
- size={multiKit === 'smallPill' ? 'small' : ''}
48
- />
49
- <Else />
50
- <FormPill
51
- closeProps={removeProps}
52
- marginRight="xs"
53
- size={multiKit === 'smallPill' ? 'small' : ''}
54
- text={label}
55
- />
56
- </If>
57
- </If>
58
- </components.MultiValueContainer>
59
- )
60
- }
61
-
62
- export default MultiValue
@@ -1,39 +0,0 @@
1
- /* @flow */
2
-
3
- import React from 'react'
4
- import { components } from 'react-select'
5
-
6
- import User from '../../pb_user/_user'
7
-
8
- const Option = (props: any) => {
9
- const {
10
- imageUrl,
11
- } = props.data
12
- const { valueComponent } = props.selectProps
13
-
14
- return (
15
- <components.Option {...props}>
16
- <div>
17
- <Choose>
18
- <When condition={!valueComponent && imageUrl}>
19
- <User
20
- align="left"
21
- avatarUrl={imageUrl}
22
- dark={props.selectProps.dark}
23
- name={props.label}
24
- orientation="horizontal"
25
- />
26
- </When>
27
- <When condition={valueComponent}>
28
- { valueComponent(props.data) }
29
- </When>
30
- <Otherwise>
31
- {props.label}
32
- </Otherwise>
33
- </Choose>
34
- </div>
35
- </components.Option>
36
- )
37
- }
38
-
39
- export default Option