playbook_ui 14.6.2.pre.alpha.PBNTR576tooltiptruncatedformpills4304 → 14.6.2.pre.alpha.PBNTR633dropdownavailablepropstable4305

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ecc1c466ffb02f3bc53b3e5237a09734fa63537829c7a4602ea17c2cf54f8d4
4
- data.tar.gz: 90a09dc18273b805231bc2657bb1d4cb953329a2e56bc8018002fbf31f65bb71
3
+ metadata.gz: 31ad89e3fa840597a7d38316aea7fcdd57bf7c4c1352e762d2845fc689346231
4
+ data.tar.gz: 519831d474fdc0187abeadbdc328f4653fdaf566195596ca5f5c600be3214d1d
5
5
  SHA512:
6
- metadata.gz: 991aee43ea52beb462030837fff91e73869d23cc1121188427c880b67a77db574b8ff9b56686e054e66f744afe5f6d2a71bf55c29d761073e478280d7e70dff7
7
- data.tar.gz: ec959956157c06abfd37e1fb04e118c012c067229045251faf52202c40bb205924702991409a7de939e016d8c8507ae37682ccd694c2cd63c89c8c0f4e122072
6
+ metadata.gz: a0538a8f59b5c77c623501feb8f0b75a5cb39aa3238debd67ca27ec09f3ddbd59bb4562c14fd54edd6bf3fdd3ca86a570ecf4d71a998bcc68e6b7992be2731e7
7
+ data.tar.gz: 9f7217f4ef982eb0e30e0f96687e8dfd0f281267397698e576d5a3af4462b07c2bab5a11877057936d8f829c3df83e6f6d60ea903ecdf13c416d4d56a552aeb2
@@ -26,6 +26,7 @@ type CurrencyProps = {
26
26
  variant?: 'default' | 'light' | 'bold',
27
27
  unit?: string,
28
28
  unstyled?: boolean,
29
+ commaSeparator?: boolean,
29
30
  }
30
31
 
31
32
  const sizes: {lg: 1, md: 3, sm: 4} = {
@@ -53,6 +54,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
53
54
  variant = 'default',
54
55
  dark = false,
55
56
  unstyled = false,
57
+ commaSeparator = false,
56
58
  } = props
57
59
 
58
60
  const emphasizedClass = emphasized ? '' : '_deemphasized'
@@ -74,7 +76,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
74
76
  className
75
77
  )
76
78
 
77
- const getFormattedNumber = (input: number | any ) => new Intl.NumberFormat('en-US', {
79
+ const getFormattedNumber = (input: number | any) => new Intl.NumberFormat('en-US', {
78
80
  notation: 'compact',
79
81
  maximumFractionDigits: 1,
80
82
  }).format(input)
@@ -88,12 +90,20 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
88
90
  return isAmount ? num.slice(0, -1) : isUnit ? num.slice(-1) : ''
89
91
  }
90
92
 
91
- const getMatchingDecimalAmount = decimals === "matching" ? amount : whole,
92
- getMatchingDecimalValue = decimals === "matching" ? '' : `.${decimal}`
93
+ const getMatchingDecimalAmount = decimals === "matching" ? amount : whole
94
+ const getMatchingDecimalValue = decimals === "matching" ? '' : `.${decimal}`
93
95
 
94
- const getAmount = abbreviate ? getAbbreviatedValue('amount') : getMatchingDecimalAmount,
95
- getAbbreviation = abbreviate ? getAbbreviatedValue('unit') : null,
96
- getDecimalValue = abbreviate ? '' : getMatchingDecimalValue
96
+ const formatAmount = (amount: string) => {
97
+ if (!commaSeparator) return amount;
98
+
99
+ const [wholePart, decimalPart] = amount.split('.');
100
+ const formattedWhole = new Intl.NumberFormat('en-US').format(parseInt(wholePart));
101
+ return decimalPart ? `${formattedWhole}.${decimalPart}` : formattedWhole;
102
+ }
103
+
104
+ const getAmount = abbreviate ? getAbbreviatedValue('amount') : formatAmount(getMatchingDecimalAmount)
105
+ const getAbbreviation = abbreviate ? getAbbreviatedValue('unit') : null
106
+ const getDecimalValue = abbreviate ? '' : getMatchingDecimalValue
97
107
 
98
108
  return (
99
109
  <div
@@ -43,6 +43,9 @@ module Playbook
43
43
  prop :unstyled, type: Playbook::Props::Boolean,
44
44
  default: false
45
45
 
46
+ prop :comma_separator, type: Playbook::Props::Boolean,
47
+ default: false
48
+
46
49
  def classname
47
50
  generate_classname("pb_currency_kit", align, size, dark_class)
48
51
  end
@@ -65,7 +68,7 @@ module Playbook
65
68
  def title_props
66
69
  {
67
70
  size: size_value,
68
- text: abbreviate ? abbreviated_value : whole_value,
71
+ text: abbreviate ? abbreviated_value : formatted_amount,
69
72
  classname: "pb_currency_value",
70
73
  dark: dark,
71
74
  }
@@ -96,28 +99,38 @@ module Playbook
96
99
  private
97
100
 
98
101
  def whole_value
99
- return amount if decimals == "matching"
100
-
101
- amount.split(".").first.to_s
102
+ value = amount.split(".").first
103
+ if comma_separator
104
+ number_with_delimiter(value.gsub(",", ""))
105
+ else
106
+ value
107
+ end
102
108
  end
103
109
 
104
- def abbreviated_value(index = 0..-2)
105
- value = amount.split(".").first.split(",").join("")
106
- abbreviated_num = number_to_human(value, units: { thousand: "K", million: "M", billion: "B", trillion: "T" }).gsub(/\s+/, "").to_s
107
- abbreviated_num[index]
110
+ def decimal_value
111
+ amount.split(".")[1] || "00"
108
112
  end
109
113
 
110
114
  def units_element
111
115
  return "" if decimals == "matching" && !abbreviate && !unit
112
116
 
113
- _, decimal_part = amount.split(".")
114
- if unit.nil? && abbreviate == false
115
- decimal_part.nil? ? ".00" : ".#{decimal_part}"
117
+ if unit.nil? && !abbreviate
118
+ if decimals == "matching"
119
+ ""
120
+ else
121
+ ".#{decimal_value}"
122
+ end
116
123
  else
117
124
  abbreviate ? "#{abbreviated_value(-1)}#{unit}" : unit
118
125
  end
119
126
  end
120
127
 
128
+ def abbreviated_value(index = 0..-2)
129
+ value = amount.split(".").first.gsub(",", "").to_i
130
+ abbreviated_num = number_to_human(value, units: { thousand: "K", million: "M", billion: "B", trillion: "T" }).gsub(/\s+/, "")
131
+ abbreviated_num[index]
132
+ end
133
+
121
134
  def size_value
122
135
  case size
123
136
  when "lg"
@@ -132,6 +145,20 @@ module Playbook
132
145
  def dark_class
133
146
  dark ? "dark" : nil
134
147
  end
148
+
149
+ def formatted_amount
150
+ return abbreviated_value if abbreviate
151
+
152
+ if decimals == "matching"
153
+ if comma_separator
154
+ number_with_delimiter(amount.gsub(",", ""))
155
+ else
156
+ amount
157
+ end
158
+ else
159
+ whole_value
160
+ end
161
+ end
135
162
  end
136
163
  end
137
164
  end
@@ -61,3 +61,38 @@ test('decimals default prop returns decimals as body text', () => {
61
61
  expect(currencyKit.querySelector('.pb_currency_value')).toHaveTextContent('320')
62
62
  expect(currencyKit.querySelector('.unit')).toHaveTextContent('.20')
63
63
  })
64
+
65
+
66
+ test('commaSeparator prop returns comma separated amount', () => {
67
+ render(
68
+ <Currency
69
+ amount="1234567890"
70
+ commaSeparator
71
+ data={{ testid: 'comma-test' }}
72
+ />
73
+ )
74
+ expect(screen.getByTestId('comma-test')).toHaveTextContent('1,234,567,890')
75
+ })
76
+
77
+ test('commaSeparator prop returns comma separated amount with decimals', () => {
78
+ render(
79
+ <Currency
80
+ amount="1234567890.12"
81
+ commaSeparator
82
+ data={{ testid: 'comma-test-decimals' }}
83
+ />
84
+ )
85
+ expect(screen.getByTestId('comma-test-decimals')).toHaveTextContent('1,234,567,890.12')
86
+ })
87
+
88
+ test('commaSeparator prop returns comma separated amount with decimals="matching"', () => {
89
+ render(
90
+ <Currency
91
+ amount="1234567890.12"
92
+ commaSeparator
93
+ data={{ testid: 'comma-test-decimals-matching' }}
94
+ decimals="matching"
95
+ />
96
+ )
97
+ expect(screen.getByTestId('comma-test-decimals-matching')).toHaveTextContent('1,234,567,890.12')
98
+ })
@@ -0,0 +1,7 @@
1
+ <%= pb_rails("currency", props: {
2
+ amount: '1234567.89',
3
+ comma_separator: true,
4
+ size: 'lg',
5
+ emphasized: false,
6
+ decimals: 'matching',
7
+ }) %>
@@ -0,0 +1,18 @@
1
+ import React from "react"
2
+
3
+ import Currency from "../_currency"
4
+
5
+ const CurrencyCommaSeparator = (props) => {
6
+ return (
7
+ <Currency
8
+ amount='1234567.89'
9
+ commaSeparator
10
+ decimals="matching"
11
+ emphasized={false}
12
+ size="lg"
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ export default CurrencyCommaSeparator
@@ -0,0 +1,3 @@
1
+ The optional `commaSeparator` can be used to auto-format the use of commas as a thousands separator.
2
+
3
+ **NOTE:** If the value passed into the `amount` prop is already comma-dilineated, it will not add additional commas.
@@ -8,7 +8,8 @@ examples:
8
8
  - currency_abbreviated: Abbreviate Larger Amounts
9
9
  - currency_matching_decimals: Matching Decimals
10
10
  - currency_unstyled: Unstyled
11
-
11
+ - currency_comma_separator: Comma Separator
12
+
12
13
  react:
13
14
  - currency_variants: Variants
14
15
  - currency_size: Size
@@ -17,6 +18,7 @@ examples:
17
18
  - currency_abbreviated: Abbreviate Larger Amounts
18
19
  - currency_matching_decimals: Matching Decimals
19
20
  - currency_unstyled: Unstyled
21
+ - currency_comma_separator: Comma Separator
20
22
 
21
23
  swift:
22
24
  - currency_size_swift: Size
@@ -5,3 +5,4 @@ export { default as CurrencyNoSymbol } from './_currency_no_symbol.jsx'
5
5
  export { default as CurrencyAbbreviated } from './_currency_abbreviated.jsx'
6
6
  export { default as CurrencyMatchingDecimals } from './_currency_matching_decimals.jsx'
7
7
  export { default as CurrencyUnstyled } from './_currency_unstyled.jsx'
8
+ export { default as CurrencyCommaSeparator } from './_currency_comma_separator.jsx'
@@ -47,7 +47,7 @@ interface DropdownComponent
47
47
  Container: typeof DropdownContainer;
48
48
  }
49
49
 
50
- const Dropdown = forwardRef((props: DropdownProps, ref: any) => {
50
+ const Dropdown: React.ForwardRefRenderFunction<unknown, DropdownProps> = (props, ref) => {
51
51
  const {
52
52
  aria = {},
53
53
  autocomplete = false,
@@ -260,7 +260,8 @@ const Dropdown = forwardRef((props: DropdownProps, ref: any) => {
260
260
  <DropdownContainer>
261
261
  {optionsWithBlankSelection &&
262
262
  optionsWithBlankSelection?.map((option: GenericObject) => (
263
- <Dropdown.Option key={option.id}
263
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
264
+ <ForwardedDropdown.Option key={option.id}
264
265
  option={option}
265
266
  />
266
267
  ))}
@@ -278,11 +279,12 @@ const Dropdown = forwardRef((props: DropdownProps, ref: any) => {
278
279
  </DropdownContext.Provider>
279
280
  </div>
280
281
  )
281
- }) as DropdownComponent
282
+ }
282
283
 
283
- Dropdown.displayName = "Dropdown";
284
- Dropdown.Option = DropdownOption;
285
- Dropdown.Trigger = DropdownTrigger;
286
- Dropdown.Container = DropdownContainer;
284
+ const ForwardedDropdown = forwardRef(Dropdown) as DropdownComponent;
285
+ ForwardedDropdown.displayName = "Dropdown";
286
+ ForwardedDropdown.Option = DropdownOption;
287
+ ForwardedDropdown.Trigger = DropdownTrigger;
288
+ ForwardedDropdown.Container = DropdownContainer;
287
289
 
288
- export default Dropdown;
290
+ export default ForwardedDropdown;
@@ -142,9 +142,7 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
142
142
  height: 12px !important;
143
143
  width: 12px !important;
144
144
  padding-right: $space_xs;
145
- + .pb_form_pill_text, + .pb_form_pill_tag,
146
- + .pb_tooltip_kit .pb_form_pill_text, + .pb_tooltip_kit .pb_form_pill_tag,
147
- + div .pb_form_pill_text, + div .pb_form_pill_tag {
145
+ + .pb_form_pill_text, + .pb_form_pill_tag {
148
146
  padding-left: 0;
149
147
  }
150
148
  }
@@ -171,9 +169,7 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
171
169
  }
172
170
  .pb_form_pill_icon {
173
171
  padding-right: $space_xxs;
174
- + .pb_form_pill_text, + .pb_form_pill_tag,
175
- + .pb_tooltip_kit .pb_form_pill_text, + .pb_tooltip_kit .pb_form_pill_tag,
176
- + div .pb_form_pill_text, + div .pb_form_pill_tag {
172
+ + .pb_form_pill_text, + .pb_form_pill_tag {
177
173
  padding-left: 0;
178
174
  }
179
175
  }
@@ -3,7 +3,6 @@ import classnames from 'classnames'
3
3
  import Title from '../pb_title/_title'
4
4
  import Icon from '../pb_icon/_icon'
5
5
  import Avatar from '../pb_avatar/_avatar'
6
- import Tooltip from '../pb_tooltip/_tooltip'
7
6
  import { globalProps, GlobalProps } from '../utilities/globalProps'
8
7
  import { buildDataProps, buildHtmlProps } from '../utilities/props'
9
8
 
@@ -63,30 +62,6 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
63
62
  const dataProps = buildDataProps(data)
64
63
  const htmlProps = buildHtmlProps(htmlOptions)
65
64
 
66
- const renderTitle = (content: string, className: string) => {
67
- const titleComponent = (
68
- <Title
69
- className={className}
70
- size={4}
71
- text={content}
72
- truncate={props.truncate}
73
- />
74
- )
75
- if (props.truncate) {
76
- return (
77
- <Tooltip
78
- interaction
79
- placement="top"
80
- position="fixed"
81
- text={content}
82
- >
83
- {titleComponent}
84
- </Tooltip>
85
- )
86
- }
87
- return titleComponent
88
- }
89
-
90
65
  return (
91
66
  <div className={css}
92
67
  id={id}
@@ -102,7 +77,12 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
102
77
  size="xxs"
103
78
  status={null}
104
79
  />
105
- {renderTitle(name, "pb_form_pill_text")}
80
+ <Title
81
+ className="pb_form_pill_text"
82
+ size={4}
83
+ text={name}
84
+ truncate={props.truncate}
85
+ />
106
86
  </>
107
87
  )}
108
88
  {((name && icon && !text) || (name && icon && text)) && (
@@ -113,7 +93,12 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
113
93
  size="xxs"
114
94
  status={null}
115
95
  />
116
- {renderTitle(name, "pb_form_pill_text")}
96
+ <Title
97
+ className="pb_form_pill_text"
98
+ size={4}
99
+ text={name}
100
+ truncate={props.truncate}
101
+ />
117
102
  <Icon
118
103
  className="pb_form_pill_icon"
119
104
  color={color}
@@ -128,10 +113,22 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
128
113
  color={color}
129
114
  icon={icon}
130
115
  />
131
- {renderTitle(text, "pb_form_pill_tag")}
116
+ <Title
117
+ className="pb_form_pill_tag"
118
+ size={4}
119
+ text={text}
120
+ truncate={props.truncate}
121
+ />
132
122
  </>
133
123
  )}
134
- {(!name && !icon && text) && renderTitle(text, "pb_form_pill_tag")}
124
+ {(!name && !icon && text) && (
125
+ <Title
126
+ className="pb_form_pill_tag"
127
+ size={4}
128
+ text={text}
129
+ truncate={props.truncate}
130
+ />
131
+ )}
135
132
  <div
136
133
  className="pb_form_pill_close"
137
134
  onClick={onClick}
@@ -146,5 +143,4 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
146
143
  </div>
147
144
  )
148
145
  }
149
-
150
146
  export default FormPill
@@ -13,28 +13,7 @@
13
13
  id: "typeahead-form-pill",
14
14
  is_multi: true,
15
15
  options: names,
16
- label: "Truncation Within Typeahead",
16
+ label: "Names",
17
17
  pills: true,
18
18
  truncate: 1,
19
19
  }) %>
20
-
21
- <%= pb_rails("caption", props: { text: "Form Pill Truncation" }) %>
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
- truncate: 1,
28
- }) %>
29
- <%= pb_rails("form_pill", props: {
30
- icon: "badge-check",
31
- text: "icon and a very long tag to show truncation",
32
- tabindex: 0,
33
- truncate: 1,
34
- }) %>
35
- <%= pb_rails("form_pill", props: {
36
- text: "form pill with a very long tag to show truncation",
37
- tabindex: 0,
38
- truncate: 1,
39
- }) %>
40
- <% end %>
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { Card, Caption, FormPill, Typeahead } from 'playbook-ui'
2
+ import Typeahead from '../../pb_typeahead/_typeahead'
3
3
 
4
4
  const names = [
5
5
  { label: 'Alexander Nathaniel Montgomery', value: 'Alexander Nathaniel Montgomery' },
@@ -15,34 +15,11 @@ const FormPillTruncatedText = (props) => {
15
15
  <Typeahead
16
16
  htmlOptions={{ style: { maxWidth: "240px" }}}
17
17
  isMulti
18
- label="Truncation Within Typeahead"
18
+ label="Names"
19
19
  options={names}
20
20
  truncate={1}
21
21
  {...props}
22
22
  />
23
- <Caption text="Form Pill Truncation"/>
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
- truncate={1}
31
- />
32
- <FormPill
33
- icon="badge-check"
34
- onClick={() => {alert('Click!')}}
35
- tabIndex={0}
36
- text="icon and a very long tag to show truncation"
37
- truncate={1}
38
- />
39
- <FormPill
40
- onClick={() => {alert('Click!')}}
41
- tabIndex={0}
42
- text="form pill with a very long tag to show truncation"
43
- truncate={1}
44
- />
45
- </Card>
46
23
  </>
47
24
  )
48
25
  }
@@ -1 +1 @@
1
- For pills with longer text, the `truncate` global prop can be used to truncate the label within each Form Pill. Hover over the truncated Form Pill and a Tooltip containing the text or tag section of the Form Pill will appear. See [here](https://playbook.powerapp.cloud/visual_guidelines/truncate) for more information on the truncate global prop.
1
+ For pills with longer text, the `truncate` global prop can be used to truncate the label within each Form Pill. See [here](https://playbook.powerapp.cloud/visual_guidelines/truncate) for more information on the truncate global prop.
@@ -1,51 +1,19 @@
1
1
  <%= content_tag(:div, id: object.id, data: object.data, class: object.classname + object.size_class, tabindex: object.tabindex, **combined_html_options) do %>
2
2
  <% if object.name.present? %>
3
3
  <%= pb_rails("avatar", props: { name: object.name, image_url: object.avatar_url, size: "xxs" }) %>
4
- <% element_id = "pill_#{object.name.parameterize}" %>
5
- <div>
6
- <%= pb_rails("title", props: {
7
- classname: "pb_form_pill_text #{object.truncate ? "truncate_#{object.truncate}" : ""}",
8
- id: element_id,
9
- size: 4,
10
- text: object.name,
11
- }) %>
12
- <% if object.truncate %>
13
- <%= pb_rails("tooltip", props: {
14
- position: "top",
15
- tooltip_id: "tooltip-#{element_id}",
16
- trigger_element_selector: "##{element_id}"
17
- }) do %>
18
- <%= object.name %>
19
- <% end %>
20
- <% end %>
21
- </div>
4
+ <%= pb_rails("title", props: { text: object.name, size: 4, classname: "pb_form_pill_text" }) %>
22
5
  <% if object.icon.present? %>
23
6
  <%= pb_rails("icon", props: { classname: "pb_form_pill_icon", color: object.color, icon: object.icon }) %>
24
7
  <% end %>
25
8
  <% elsif object.text.present? %>
26
- <% if object.icon.present? %>
27
- <%= pb_rails("icon", props: { classname: "pb_form_pill_icon", color: object.color, icon: object.icon }) %>
28
- <% end %>
29
- <% element_id = "pill_#{object.text.parameterize}" %>
30
- <div>
31
- <%= pb_rails("title", props: {
32
- classname: "pb_form_pill_tag #{object.truncate ? "truncate_#{object.truncate}" : ""}",
33
- id: element_id,
34
- size: 4,
35
- text: object.text
36
- }) %>
37
- <% if object.truncate %>
38
- <%= pb_rails("tooltip", props: {
39
- position: "top",
40
- tooltip_id: "tooltip-#{element_id}",
41
- trigger_element_selector: "##{element_id}"
42
- }) do %>
43
- <%= object.text %>
44
- <% end %>
9
+ <% if object.icon.present? %>
10
+ <%= pb_rails("icon", props: { classname: "pb_form_pill_icon", color: object.color, icon: object.icon }) %>
11
+ <% end %>
12
+ <% if object.text.present? %>
13
+ <%= pb_rails("title", props: { text: object.text, size: 4, classname: "pb_form_pill_tag" }) %>
45
14
  <% end %>
46
- </div>
47
15
  <% end %>
48
16
  <%= pb_rails("body", props: { classname: "pb_form_pill_close" }) do %>
49
17
  <%= pb_rails("icon", props: { icon: 'times', fixed_width: true, size: object.close_icon_size }) %>
50
18
  <% end %>
51
- <% end %>
19
+ <% end %>