playbook_ui 14.8.0.pre.rc.8 → 14.9.0.pre.alpha.pbntr700newresettodefaultprop4736

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.html.erb +1 -1
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta_sort.html.erb +1 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell_rails.html.erb +53 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell_rails.md +5 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +3 -1
  9. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +15 -0
  10. data/app/pb_kits/playbook/pb_background/_background.tsx +8 -2
  11. data/app/pb_kits/playbook/pb_button/_button.scss +6 -0
  12. data/app/pb_kits/playbook/pb_button/_button.tsx +1 -3
  13. data/app/pb_kits/playbook/pb_button/_button_mixins.scss +15 -0
  14. data/app/pb_kits/playbook/pb_button/button.rb +1 -1
  15. data/app/pb_kits/playbook/pb_button/docs/_button_default.html.erb +1 -0
  16. data/app/pb_kits/playbook/pb_button/docs/_button_default.jsx +8 -0
  17. data/app/pb_kits/playbook/pb_button/docs/_button_default.md +1 -1
  18. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +2 -2
  19. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +0 -4
  20. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +84 -7
  21. data/app/pb_kits/playbook/pb_collapsible/_collapsible.tsx +3 -1
  22. data/app/pb_kits/playbook/pb_currency/_currency.tsx +7 -3
  23. data/app/pb_kits/playbook/pb_currency/currency.html.erb +2 -2
  24. data/app/pb_kits/playbook/pb_currency/currency.rb +17 -1
  25. data/app/pb_kits/playbook/pb_currency/currency.test.js +40 -3
  26. data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.html.erb +4 -0
  27. data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.jsx +16 -0
  28. data/app/pb_kits/playbook/pb_currency/docs/example.yml +2 -0
  29. data/app/pb_kits/playbook/pb_currency/docs/index.js +1 -0
  30. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +5 -0
  31. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +10 -0
  32. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +1 -0
  33. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +1 -0
  34. data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +159 -45
  35. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +31 -0
  36. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.md +6 -0
  37. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -1
  38. data/app/pb_kits/playbook/pb_drawer/docs/index.js +1 -0
  39. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -0
  40. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +0 -1
  41. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +0 -4
  42. data/app/pb_kits/playbook/pb_dropdown/utilities/subComponentHelper.tsx +13 -2
  43. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +4 -3
  44. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.html.erb +1 -1
  45. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +63 -12
  46. data/app/pb_kits/playbook/pb_image/_image.tsx +3 -1
  47. data/app/pb_kits/playbook/pb_layout/_layout.tsx +6 -3
  48. data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +3 -1
  49. data/app/pb_kits/playbook/pb_progress_simple/_progress_simple.tsx +5 -3
  50. data/app/pb_kits/playbook/pb_progress_simple/progress_simple.html.erb +3 -2
  51. data/app/pb_kits/playbook/pb_progress_simple/progress_simple.rb +5 -0
  52. data/app/pb_kits/playbook/pb_section_separator/_section_separator.tsx +3 -1
  53. data/app/pb_kits/playbook/pb_selectable_card/docs/_selectable_card_default.html.erb +2 -1
  54. data/app/pb_kits/playbook/pb_table/_table.tsx +109 -25
  55. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.jsx +87 -0
  56. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_react.md +2 -0
  57. data/app/pb_kits/playbook/pb_table/docs/index.js +1 -0
  58. data/app/pb_kits/playbook/pb_table/styles/_all.scss +2 -0
  59. data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +4 -0
  60. data/app/pb_kits/playbook/pb_table/styles/_sticky_columns.scss +18 -0
  61. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.html.erb +47 -0
  62. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.jsx +59 -0
  63. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +3 -0
  64. data/app/pb_kits/playbook/pb_typeahead/index.ts +29 -3
  65. data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +5 -2
  66. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +4 -0
  67. data/app/pb_kits/playbook/tokens/_height.scss +19 -0
  68. data/app/pb_kits/playbook/tokens/exports/_height.module.scss +37 -0
  69. data/app/pb_kits/playbook/utilities/_height.scss +33 -0
  70. data/app/pb_kits/playbook/utilities/_max_width.scss +29 -9
  71. data/app/pb_kits/playbook/utilities/_min_width.scss +6 -2
  72. data/app/pb_kits/playbook/utilities/_width.scss +45 -0
  73. data/app/pb_kits/playbook/utilities/globalPropNames.mjs +1 -1
  74. data/app/pb_kits/playbook/utilities/globalProps.ts +37 -4
  75. data/dist/chunks/_typeahead-DU1QgR52.js +22 -0
  76. data/dist/chunks/_weekday_stacked-BLOmRNnB.js +45 -0
  77. data/dist/chunks/{lib-BC6ESsxG.js → lib-Ce7MLbJk.js} +1 -1
  78. data/dist/chunks/{pb_form_validation-B_Z9rEbg.js → pb_form_validation-kPWA1Z2g.js} +1 -1
  79. data/dist/chunks/vendor.js +1 -1
  80. data/dist/menu.yml +321 -0
  81. data/dist/playbook-doc.js +1 -1
  82. data/dist/playbook-rails-react-bindings.js +1 -1
  83. data/dist/playbook-rails.js +1 -1
  84. data/dist/playbook.css +1 -1
  85. data/lib/playbook/classnames.rb +4 -0
  86. data/lib/playbook/forms/builder/typeahead_field.rb +13 -0
  87. data/lib/playbook/height.rb +29 -0
  88. data/lib/playbook/kit_base.rb +16 -1
  89. data/lib/playbook/max_height.rb +29 -0
  90. data/lib/playbook/min_height.rb +29 -0
  91. data/lib/playbook/spacing.rb +21 -0
  92. data/lib/playbook/version.rb +2 -2
  93. metadata +23 -6
  94. data/dist/chunks/_typeahead-D0PihN_3.js +0 -22
  95. data/dist/chunks/_weekday_stacked-uMIX8f-A.js +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 159aa5912d4438299f532e67b05c99473971120a346c9f075e0579665d33e617
4
- data.tar.gz: c8fa8e2f5e6f4b0f5f042beed36ebdbd08c88e2dfc49e7b79700d380a8346c6a
3
+ metadata.gz: ed2801ec0227abe6135982abb6b527499bfd93c6bdb9f60abeb128b177e7b86f
4
+ data.tar.gz: b48246eb5583601ec41ef7ae8fcdb8f3ca8f50b481f634de6b596f5b82ff1692
5
5
  SHA512:
6
- metadata.gz: a92b149c064b4c941df5a1af10c530cc6f1a38f378218740785feea998210fd8c59e628f2d2655b08b8fc37f77bc9e695163f82fc5e1b7ce75fb6304296cc9f1
7
- data.tar.gz: 69f2230fc57351ad61ccedffd73063d4282e36804cd2c2a64b6ae94d89961c5561bd73bdb9f57e379ff24274f6bc5234484efe965da5d81abd196e08e1d5d640
6
+ metadata.gz: 21ae6b48959d1c92fe17977b28386e1d63db657cfed8b4494ed0dccecce97011918631f336ea06dfc008dca129c41d889b31e6cb0bdd6cf74ffc55285ea4710f
7
+ data.tar.gz: 2944e11aca37b9ff421f1404eec2e91a552bb59a11ff3058bd9ab4e5c1cfdc3d6a5c5c2a74f642591c6c6af5a3a03c247698ef47e05e7fe315b1fc37379ebe07
@@ -111,6 +111,7 @@
111
111
  @import 'utilities/mixins';
112
112
  @import 'utilities/spacing';
113
113
  @import 'utilities/cursor';
114
+ @import 'utilities/width';
114
115
  @import 'utilities/min_width';
115
116
  @import 'utilities/max_width';
116
117
  @import 'utilities/positioning';
@@ -126,3 +127,4 @@
126
127
  @import 'utilities/overflow';
127
128
  @import 'utilities/truncate';
128
129
  @import 'utilities/vertical_align';
130
+ @import 'utilities/height';
@@ -30,4 +30,4 @@
30
30
  }
31
31
  ] %>
32
32
 
33
- <%= pb_rails("advanced_table", props: {table_data: @table_data, column_definitions: column_definitions}) %>
33
+ <%= pb_rails("advanced_table", props: { id: "beta_table", table_data: @table_data, column_definitions: column_definitions }) %>
@@ -55,5 +55,5 @@
55
55
 
56
56
  <%= pb_rails("advanced_table", props: { table_data: @table_data, column_definitions: column_definitions }) do %>
57
57
  <%= pb_rails("advanced_table/table_header", props: { column_definitions: column_definitions }) %>
58
- <%= pb_rails("advanced_table/table_body", props: { id: "subrow_headers", table_data: @table_data, column_definitions: column_definitions, subrow_headers: subrow_headers, enable_toggle_expansion: "all" }) %>
58
+ <%= pb_rails("advanced_table/table_body", props: { id: "beta_sort", table_data: @table_data, column_definitions: column_definitions, subrow_headers: subrow_headers, enable_toggle_expansion: "all" }) %>
59
59
  <% end %>
@@ -0,0 +1,53 @@
1
+ <%
2
+ column_definitions = [
3
+ {
4
+ accessor: "year",
5
+ label: "Year",
6
+ cellAccessors: ["quarter", "month", "day"],
7
+ custom_renderer: ->(row, value) {
8
+ capture do
9
+ pb_rails("flex") do
10
+ pb_rails("title", props: { text: value, size: 4 }) +
11
+ pb_rails("badge", props: { dark: true, margin_left: "xxs", text: row[:newEnrollments].to_i > 20 ? "High" : "Low", variant: "neutral" })
12
+ end
13
+ end
14
+ }
15
+ },
16
+ {
17
+ accessor: "newEnrollments",
18
+ label: "New Enrollments",
19
+ custom_renderer: ->(row, value) { pb_rails("pill", props: { text: value, variant: "success" }) }
20
+ },
21
+ {
22
+ accessor: "scheduledMeetings",
23
+ label: "Scheduled Meetings",
24
+ custom_renderer: ->(row, value) { content_tag(:a, value, href: "#") }
25
+ },
26
+ {
27
+ accessor: "attendanceRate",
28
+ label: "Attendance Rate",
29
+ custom_renderer: ->(row, value) {
30
+ capture do
31
+ pb_rails("flex", props: { align_items: "end", orientation: "column" }) do
32
+ pb_rails("detail", props: { bold: true, color: "default", text: value }) +
33
+ pb_rails("caption", props: { size: "xs", text: row[:graduatedStudents] })
34
+ end
35
+ end
36
+ }
37
+ },
38
+ {
39
+ accessor: "completedClasses",
40
+ label: "Completed Classes",
41
+ },
42
+ {
43
+ accessor: "classCompletionRate",
44
+ label: "Class Completion Rate",
45
+ },
46
+ {
47
+ accessor: "graduatedStudents",
48
+ label: "Graduated Students",
49
+ }
50
+ ]
51
+ %>
52
+
53
+ <%= pb_rails("advanced_table", props: { id: "custom_cell", table_data: @table_data, column_definitions: column_definitions }) %>
@@ -0,0 +1,5 @@
1
+ The Advanced Table also allows for rendering custom components within individual Cells. To achieve this, you can make use of the optional `custom_renderer` item within each column_definitions. This function gives you access to the current Cell's value if you just want to use that with a custom Kit, but it also gives you access to the entire `row` object. The row object provides all data for the current row.
2
+
3
+ See [here](https://playbook.powerapp.cloud/kits/advanced_table/rails#column_definitions) for more indepth information on column_definitions are how to use them.
4
+
5
+ See [here](https://github.com/powerhome/playbook/tree/master/playbook/app/pb_kits/playbook/pb_advanced_table#readme) for the structure of the table_data used.
@@ -3,6 +3,7 @@ examples:
3
3
  - advanced_table_beta: Default (Required Props)
4
4
  - advanced_table_beta_subrow_headers: SubRow Headers
5
5
  - advanced_table_beta_sort: Enable Sorting
6
+ - advanced_table_custom_cell_rails: Custom Components for Cells
6
7
 
7
8
  react:
8
9
  - advanced_table_default: Default (Required Props)
@@ -11,7 +11,9 @@
11
11
  </button>
12
12
  <% end %>
13
13
  <%= pb_rails("flex/flex_item", props:{padding_left: index.zero? && object.row[:children].present? ? "none" : "xs"}) do %>
14
- <% if index.zero? %>
14
+ <% if column[:custom_renderer].present? %>
15
+ <%= raw(column[:custom_renderer].call(object.row, custom_renderer_value(column, index))) %>
16
+ <% elsif index.zero? %>
15
17
  <% if object.depth.zero? %>
16
18
  <%= object.row[column[:accessor].to_sym] %>
17
19
  <% else %>
@@ -26,6 +26,21 @@ module Playbook
26
26
 
27
27
  private
28
28
 
29
+ def custom_renderer_value(column, index)
30
+ if index.zero?
31
+ if depth.zero?
32
+ row[column[:accessor].to_sym]
33
+ else
34
+ depth_accessors.each_with_index do |item, accessor_index|
35
+ key = item.to_sym
36
+ return row[key] if depth - 1 == accessor_index
37
+ end
38
+ end
39
+ else
40
+ row[column[:accessor].to_sym]
41
+ end
42
+ end
43
+
29
44
  def subrow_depth_classname
30
45
  depth.positive? ? "depth-sub-row-#{depth}" : ""
31
46
  end
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useState } from 'react'
2
2
  import classnames from 'classnames'
3
3
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
4
- import { GlobalProps, globalProps } from '../utilities/globalProps'
4
+ import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
5
5
 
6
6
  type BackgroundColors = 'gradient' |
7
7
  'dark' |'light' | 'white' | 'success' | 'warning' | 'error' | 'info' | 'neutral' | 'primary' | 'shadow' |
@@ -145,6 +145,12 @@ const Background = (props: BackgroundProps): React.ReactElement => {
145
145
  } : {})
146
146
  };
147
147
 
148
+ const dynamicInlineProps = globalInlineProps(props);
149
+ const combinedStyles = {
150
+ ...backgroundStyle,
151
+ ...dynamicInlineProps
152
+ };
153
+
148
154
  const Tag: React.ReactElement | any = `${tag}`;
149
155
  const ariaProps = buildAriaProps(aria);
150
156
  const dataProps = buildDataProps(data);
@@ -158,7 +164,7 @@ const Background = (props: BackgroundProps): React.ReactElement => {
158
164
  alt={alt}
159
165
  className={classes}
160
166
  id={id}
161
- style={backgroundStyle}
167
+ style={combinedStyles}
162
168
  >
163
169
  {children}
164
170
  </Tag>
@@ -77,6 +77,12 @@ $pb_button_sizes: (
77
77
  &[class*=_loading] {
78
78
  @include pb_button_loading(true);
79
79
  }
80
+
81
+ // Danger ===================
82
+ &[class*=_danger] {
83
+ @include pb_button_danger;
84
+ }
85
+
80
86
  // Dark Variants =============
81
87
  &.dark {
82
88
  &[class*=_primary] {
@@ -37,7 +37,7 @@ type ButtonPropTypes = {
37
37
  type?: 'inline' | null,
38
38
  htmlType?: 'submit' | 'reset' | 'button' | undefined,
39
39
  value?: string | null,
40
- variant?: 'primary' | 'secondary' | 'link'| 'reaction',
40
+ variant?: 'primary' | 'secondary' | 'link'| 'danger' | 'reaction',
41
41
  wrapperClass?: string,
42
42
  } & GlobalProps
43
43
 
@@ -206,8 +206,6 @@ const Button = (props: ButtonPropTypes): React.ReactElement => {
206
206
  <Icon icon={icon ? icon : "face-smile-plus"} />
207
207
  )
208
208
  }
209
-
210
-
211
209
  </button>
212
210
  );
213
211
  } else {
@@ -167,6 +167,21 @@ $pb_button_border_width: 0px;
167
167
  }
168
168
  }
169
169
 
170
+ // Danger ======================
171
+ @mixin pb_button_danger {
172
+ @include pb_button_variant($error, $text_dk_default, transparent);
173
+
174
+ @media (hover:hover) {
175
+ &:hover {
176
+ @include pb_button_hover($bg: darken($error, $pb_button_hover_darken));
177
+ }
178
+ &:active {
179
+ transition: none;
180
+ @include pb_button_variant($error);
181
+ }
182
+ }
183
+ }
184
+
170
185
  // Dark Primary =================
171
186
  @mixin pb_button_primary_dark{
172
187
  @include pb_button_variant($primary_action);
@@ -16,7 +16,7 @@ module Playbook
16
16
  prop :new_window, type: Playbook::Props::Boolean,
17
17
  default: false
18
18
  prop :variant, type: Playbook::Props::Enum,
19
- values: %w[primary secondary link reaction],
19
+ values: %w[primary secondary link danger reaction],
20
20
  default: "primary"
21
21
  prop :count, type: Playbook::Props::Number
22
22
  prop :highlight, type: Playbook::Props::Boolean,
@@ -2,4 +2,5 @@
2
2
  <%= pb_rails("button", props: { text: "Button Secondary", variant: "secondary", margin_right: "lg" }) %>
3
3
  <%= pb_rails("button", props: { text: "Button Link", variant: "link", margin_right: "lg" }) %>
4
4
  <%= pb_rails("button", props: { text: "Button Disabled", disabled: true, margin_right: "lg" }) %>
5
+ <%= pb_rails("button", props: { text: "Button Danger", variant: "danger", margin_right: "lg" }) %>
5
6
 
@@ -34,6 +34,14 @@ const ButtonDefault = (props) => (
34
34
  text='Button Disabled'
35
35
  {...props}
36
36
  />
37
+ <Button
38
+ marginRight='lg'
39
+ onClick={() => alert("button clicked!")}
40
+ tabIndex={0}
41
+ text='Button Danger'
42
+ variant='danger'
43
+ {...props}
44
+ />
37
45
  </div>
38
46
  )
39
47
 
@@ -1 +1 @@
1
- The primary button is used for the most important button on the page. Secondary buttons can be used for actions that are less important. Button links can be helpful for buttons that do not need a lot of attention drawn to them. Disabled buttons are used when you don't want the user to click the button.
1
+ The primary button is used for the most important button on the page. Secondary buttons can be used for actions that are less important. Button links can be helpful for buttons that do not need a lot of attention drawn to them. Disabled buttons are used when you don't want the user to click the button. Danger buttons are used to indicate destructive actions such as deleting.
@@ -6,12 +6,12 @@
6
6
  ) do %>
7
7
  <%= content.presence || object.input %>
8
8
  <% if object.indeterminate %>
9
- <span class="pb_checkbox_indeterminate">
9
+ <span data-pb-checkbox-icon-span="true" class="pb_checkbox_indeterminate">
10
10
  <%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon", fixed_width: true}) %>
11
11
  <%= pb_rails("icon", props: { icon: "check", classname: "check_icon hidden", fixed_width: true}) %>
12
12
  </span>
13
13
  <% else %>
14
- <span class="pb_checkbox_checkmark">
14
+ <span data-pb-checkbox-icon-span="true" class="pb_checkbox_checkmark">
15
15
  <%= pb_rails("icon", props: { icon: "check", classname: "check_icon", fixed_width: true}) %>
16
16
  <%= pb_rails("icon", props: { icon: "minus", classname: "indeterminate_icon hidden", fixed_width: true}) %>
17
17
  </span>
@@ -18,10 +18,6 @@ module Playbook
18
18
  prop :form_spacing, type: Playbook::Props::Boolean,
19
19
  default: false
20
20
 
21
- def checked_html
22
- checked ? "checked='true'" : nil
23
- end
24
-
25
21
  def classname
26
22
  generate_classname("pb_checkbox_kit", checked_class) + indeterminate_class + error_class
27
23
  end
@@ -1,7 +1,84 @@
1
- <%= pb_rails("checkbox" , props: {
2
- text: "Select ",
3
- value: "checkbox-value",
4
- name: "main",
5
- indeterminate: true,
6
- id: "test-indeterminate-js"
7
- }) %>
1
+ <% checkboxes = [
2
+ { name: 'Coffee', id: 'coffee', checked: false },
3
+ { name: 'Ice Cream', id: 'ice-cream', checked: false },
4
+ { name: 'Chocolate', id: 'chocolate', checked: true }
5
+ ] %>
6
+
7
+ <%= pb_rails("table", props: { container: false, size: "md" }) do %>
8
+ <thead>
9
+ <tr>
10
+ <th>
11
+ <%= pb_rails("checkbox", props: {
12
+ checked: true,
13
+ text: "Uncheck All",
14
+ value: "checkbox-value",
15
+ name: "main-checkbox",
16
+ indeterminate: true,
17
+ id: "indeterminate-checkbox"
18
+ }) %>
19
+ </th>
20
+ </tr>
21
+ </thead>
22
+
23
+ <tbody>
24
+ <% checkboxes.each do |checkbox| %>
25
+ <tr>
26
+ <td>
27
+ <%= pb_rails("checkbox", props: {
28
+ checked: checkbox[:checked],
29
+ text: checkbox[:name],
30
+ value: checkbox[:id],
31
+ name: "#{checkbox[:id]}-indeterminate-checkbox",
32
+ id: "#{checkbox[:id]}-indeterminate-checkbox",
33
+ }) %>
34
+ </td>
35
+ </tr>
36
+ <% end %>
37
+ </tbody>
38
+ <% end %>
39
+
40
+ <script>
41
+ document.addEventListener('DOMContentLoaded', function() {
42
+ const mainCheckboxWrapper = document.getElementById('indeterminate-checkbox');
43
+ const mainCheckbox = document.getElementsByName("main-checkbox")[0];
44
+ const childCheckboxes = document.querySelectorAll('input[type="checkbox"][id$="indeterminate-checkbox"]');
45
+
46
+ const updateMainCheckbox = () => {
47
+ // Count the number of checked child checkboxes
48
+ const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
49
+ // Determine if the main checkbox should be in an indeterminate state
50
+ const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
51
+
52
+ // Set the main checkbox states
53
+ mainCheckbox.indeterminate = indeterminate;
54
+ mainCheckbox.checked = checkedCount > 0;
55
+
56
+ // Determine the main checkbox label based on the number of checked checkboxes
57
+ const text = checkedCount === 0 ? 'Check All' : 'Uncheck All';
58
+
59
+ // Determine the icon class to add and remove based on the number of checked checkboxes
60
+ const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
61
+ const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
62
+
63
+ // Update main checkbox label
64
+ mainCheckboxWrapper.getElementsByClassName('pb_body_kit')[0].textContent = text;
65
+
66
+ // Add and remove the icon class to the main checkbox wrapper
67
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
68
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
69
+
70
+ // Toggle the visibility of the checkbox icon based on the indeterminate state
71
+ mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
72
+ mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
73
+ };
74
+
75
+ mainCheckbox.addEventListener('change', function() {
76
+ childCheckboxes.forEach(cb => cb.checked = this.checked);
77
+ updateMainCheckbox();
78
+ });
79
+
80
+ childCheckboxes.forEach(cb => {
81
+ cb.addEventListener('change', updateMainCheckbox);
82
+ });
83
+ });
84
+ </script>
@@ -2,7 +2,7 @@ import React, { useEffect, ReactElement } from 'react'
2
2
  import classnames from 'classnames'
3
3
  import useCollapsible from './useCollapsible'
4
4
 
5
- import { globalProps } from '../utilities/globalProps'
5
+ import { globalProps, globalInlineProps } from '../utilities/globalProps'
6
6
  import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
7
7
 
8
8
  import CollapsibleContent from './child_kits/CollapsibleContent'
@@ -75,6 +75,7 @@ const Collapsible = ({
75
75
  globalProps(props),
76
76
  className
77
77
  )
78
+ const dynamicInlineProps = globalInlineProps(props)
78
79
  return (
79
80
  <CollapsibleContext.Provider value={{ collapsed: isCollapsed, toggle, icon, iconSize, iconColor, onIconClick, onClick }}>
80
81
  <div
@@ -83,6 +84,7 @@ const Collapsible = ({
83
84
  {...htmlProps}
84
85
  className={classes}
85
86
  id={id}
87
+ style={dynamicInlineProps}
86
88
  >
87
89
  {Main ? (
88
90
  <CollapsibleMain {...mainProps}>
@@ -101,7 +101,11 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
101
101
  return decimalPart ? `${formattedWhole}.${decimalPart}` : formattedWhole;
102
102
  }
103
103
 
104
- const getAmount = abbreviate ? getAbbreviatedValue('amount') : formatAmount(getMatchingDecimalAmount)
104
+ const swapNegative = size === "sm" && symbol !== ""
105
+ const handleNegative = amount.startsWith("-") && swapNegative ? "-" : ""
106
+ const getAbsoluteAmount = (amountString: string) => amountString.replace(/^-/,'')
107
+ const getAbbrOrFormatAmount = abbreviate ? getAbbreviatedValue('amount') : formatAmount(getMatchingDecimalAmount)
108
+ const getAmount = swapNegative ? getAbsoluteAmount(getAbbrOrFormatAmount) : getAbbrOrFormatAmount
105
109
  const getAbbreviation = abbreviate ? getAbbreviatedValue('unit') : null
106
110
  const getDecimalValue = abbreviate ? '' : getMatchingDecimalValue
107
111
 
@@ -118,7 +122,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
118
122
  <div className={`pb_currency_wrapper${variantClass || emphasizedClass}`}>
119
123
  {unstyled ? (
120
124
  <>
121
- <div>{symbol}</div>
125
+ <div>{handleNegative}{symbol}</div>
122
126
  <div>{getAmount}</div>
123
127
  <div>
124
128
  {getAbbreviation}
@@ -132,7 +136,7 @@ const Currency = (props: CurrencyProps): React.ReactElement => {
132
136
  color="light"
133
137
  dark={dark}
134
138
  >
135
- {symbol}
139
+ {handleNegative}{symbol}
136
140
  </Body>
137
141
 
138
142
  <Title
@@ -3,12 +3,12 @@
3
3
 
4
4
  <div class=<%= "pb_currency_wrapper#{object.variant_class || object.emphasized_class}" %>>
5
5
  <% if object.unstyled %>
6
- <div><%= object.symbol %></div>
6
+ <div><%= object.negative_sign %><%= object.symbol %></div>
7
7
  <div><%= object.title_props[:text] %></div>
8
8
  <div><%= object.body_props[:text] %></div>
9
9
  <% else %>
10
10
  <%= pb_rails("body", props: object.currency_wrapper_props) do %>
11
- <%= object.symbol %>
11
+ <%= object.negative_sign %><%= object.symbol %>
12
12
  <% end %>
13
13
  <%= pb_rails("title", props: object.title_props) %>
14
14
  <%= pb_rails("body", props: object.body_props) %>
@@ -68,12 +68,20 @@ module Playbook
68
68
  def title_props
69
69
  {
70
70
  size: size_value,
71
- text: abbreviate ? abbreviated_value : formatted_amount,
71
+ text: swap_negative ? absolute_amount(abbr_or_format_amount) : abbr_or_format_amount,
72
72
  classname: "pb_currency_value",
73
73
  dark: dark,
74
74
  }
75
75
  end
76
76
 
77
+ def abbr_or_format_amount
78
+ abbreviate ? abbreviated_value : formatted_amount
79
+ end
80
+
81
+ def negative_sign
82
+ amount.starts_with?("-") && swap_negative ? "-" : ""
83
+ end
84
+
77
85
  def body_props
78
86
  {
79
87
  text: units_element,
@@ -159,6 +167,14 @@ module Playbook
159
167
  whole_value
160
168
  end
161
169
  end
170
+
171
+ def absolute_amount(amount_string)
172
+ amount_string.sub(/^-/, "")
173
+ end
174
+
175
+ def swap_negative
176
+ size == "sm" && symbol != ""
177
+ end
162
178
  end
163
179
  end
164
180
  end
@@ -65,7 +65,7 @@ test('decimals default prop returns decimals as body text', () => {
65
65
 
66
66
  test('commaSeparator prop returns comma separated amount', () => {
67
67
  render(
68
- <Currency
68
+ <Currency
69
69
  amount="1234567890"
70
70
  commaSeparator
71
71
  data={{ testid: 'comma-test' }}
@@ -76,7 +76,7 @@ test('commaSeparator prop returns comma separated amount', () => {
76
76
 
77
77
  test('commaSeparator prop returns comma separated amount with decimals', () => {
78
78
  render(
79
- <Currency
79
+ <Currency
80
80
  amount="1234567890.12"
81
81
  commaSeparator
82
82
  data={{ testid: 'comma-test-decimals' }}
@@ -87,7 +87,7 @@ test('commaSeparator prop returns comma separated amount with decimals', () => {
87
87
 
88
88
  test('commaSeparator prop returns comma separated amount with decimals="matching"', () => {
89
89
  render(
90
- <Currency
90
+ <Currency
91
91
  amount="1234567890.12"
92
92
  commaSeparator
93
93
  data={{ testid: 'comma-test-decimals-matching' }}
@@ -96,3 +96,40 @@ test('commaSeparator prop returns comma separated amount with decimals="matching
96
96
  )
97
97
  expect(screen.getByTestId('comma-test-decimals-matching')).toHaveTextContent('1,234,567,890.12')
98
98
  })
99
+
100
+ test('handles negative amounts correctly', () => {
101
+ render(
102
+ <>
103
+ <Currency
104
+ amount="-320"
105
+ data={{ testid: 'test-negative-default' }}
106
+ />
107
+ <Currency
108
+ abbreviate
109
+ amount="-3200000"
110
+ data={{ testid: 'test-negative-millions' }}
111
+ />
112
+ <Currency
113
+ amount="-123456.78"
114
+ commaSeparator
115
+ data={{ testid: 'test-negative-comma-decimals' }}
116
+ />
117
+ <Currency
118
+ amount="-400.50"
119
+ data={{ testid: 'test-negative-no-symbol' }}
120
+ symbol=""
121
+ />
122
+ <Currency
123
+ amount="-500.55"
124
+ data={{ testid: 'test-negative-medium-size' }}
125
+ size="md"
126
+ />
127
+ </>
128
+ )
129
+
130
+ expect(screen.getByTestId('test-negative-default')).toHaveTextContent('-$320')
131
+ expect(screen.getByTestId('test-negative-millions')).toHaveTextContent('-$3.2M')
132
+ expect(screen.getByTestId('test-negative-comma-decimals')).toHaveTextContent('-$123,456.78')
133
+ expect(screen.getByTestId('test-negative-no-symbol')).toHaveTextContent('-400.50')
134
+ expect(screen.getByTestId('test-negative-medium-size')).toHaveTextContent('$-500.55')
135
+ })
@@ -0,0 +1,4 @@
1
+ <%= pb_rails("currency", props: {
2
+ amount: "-2,000.50",
3
+ size: "sm",
4
+ }) %>
@@ -0,0 +1,16 @@
1
+ import React from 'react'
2
+
3
+ import Currency from '../_currency'
4
+
5
+ const CurrencyNegative = (props) => {
6
+ return (
7
+ <>
8
+ <Currency
9
+ amount="-2,000.50"
10
+ {...props}
11
+ />
12
+ </>
13
+ )
14
+ }
15
+
16
+ export default CurrencyNegative
@@ -9,6 +9,7 @@ examples:
9
9
  - currency_matching_decimals: Matching Decimals
10
10
  - currency_unstyled: Unstyled
11
11
  - currency_comma_separator: Comma Separator
12
+ - currency_negative: Negative
12
13
 
13
14
  react:
14
15
  - currency_variants: Variants
@@ -19,6 +20,7 @@ examples:
19
20
  - currency_matching_decimals: Matching Decimals
20
21
  - currency_unstyled: Unstyled
21
22
  - currency_comma_separator: Comma Separator
23
+ - currency_negative: Negative
22
24
 
23
25
  swift:
24
26
  - currency_size_swift: Size
@@ -6,3 +6,4 @@ 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
8
  export { default as CurrencyCommaSeparator } from './_currency_comma_separator.jsx'
9
+ export { default as CurrencyNegative } from './_currency_negative.jsx'
@@ -40,6 +40,8 @@ module Playbook
40
40
  default: {}
41
41
  prop :input_data, type: Playbook::Props::HashProp,
42
42
  default: {}
43
+ prop :input_options, type: Playbook::Props::HashProp,
44
+ default: {}
43
45
  prop :max_date, type: Playbook::Props::String
44
46
  prop :min_date, type: Playbook::Props::String
45
47
  prop :name, type: Playbook::Props::String
@@ -55,6 +57,8 @@ module Playbook
55
57
  prop :position, type: Playbook::Props::String,
56
58
  default: "auto"
57
59
  prop :position_element, type: Playbook::Props::String
60
+ prop :reset_to_default, type: Playbook::Props::Boolean,
61
+ default: false
58
62
  prop :scroll_container, type: Playbook::Props::String
59
63
  prop :selection_type, type: Playbook::Props::Enum,
60
64
  values: %w[week month quickpick none],
@@ -98,6 +102,7 @@ module Playbook
98
102
  plugins: plugins,
99
103
  position: position,
100
104
  positionElement: position_element,
105
+ resetToDefault: reset_to_default,
101
106
  required: required,
102
107
  selectionType: selection_type,
103
108
  showTimezone: show_timezone,