playbook_ui 14.8.0 → 14.9.0.pre.alpha.PBNTR702stickyleftcolrails4806
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +61 -17
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.html.erb +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta_sort.html.erb +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell_rails.html.erb +53 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell_rails.md +5 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.jsx +50 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.jsx +57 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.md +5 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_pagination_mock_data.json +5600 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +15 -0
- data/app/pb_kits/playbook/pb_background/_background.tsx +8 -2
- data/app/pb_kits/playbook/pb_button/_button.scss +6 -0
- data/app/pb_kits/playbook/pb_button/_button.tsx +1 -3
- data/app/pb_kits/playbook/pb_button/_button_mixins.scss +15 -0
- data/app/pb_kits/playbook/pb_button/button.rb +1 -1
- data/app/pb_kits/playbook/pb_button/docs/_button_default.html.erb +1 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_default.jsx +8 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_default.md +1 -1
- data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +2 -2
- data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +0 -4
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +84 -7
- data/app/pb_kits/playbook/pb_collapsible/_collapsible.tsx +3 -1
- data/app/pb_kits/playbook/pb_currency/_currency.tsx +7 -3
- data/app/pb_kits/playbook/pb_currency/currency.html.erb +2 -2
- data/app/pb_kits/playbook/pb_currency/currency.rb +17 -1
- data/app/pb_kits/playbook/pb_currency/currency.test.js +40 -3
- data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.html.erb +4 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_negative.jsx +16 -0
- data/app/pb_kits/playbook/pb_currency/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_currency/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_drawer/_drawer.scss +1 -0
- data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +159 -45
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +31 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.md +6 -0
- data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -1
- data/app/pb_kits/playbook/pb_drawer/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +0 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +0 -4
- data/app/pb_kits/playbook/pb_dropdown/utilities/subComponentHelper.tsx +13 -2
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +2 -2
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.html.erb +1 -1
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +63 -12
- data/app/pb_kits/playbook/pb_image/_image.tsx +3 -1
- data/app/pb_kits/playbook/pb_layout/_layout.tsx +6 -3
- data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +3 -1
- data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +2 -2
- data/app/pb_kits/playbook/pb_progress_simple/_progress_simple.tsx +5 -3
- data/app/pb_kits/playbook/pb_progress_simple/progress_simple.html.erb +3 -2
- data/app/pb_kits/playbook/pb_progress_simple/progress_simple.rb +5 -0
- data/app/pb_kits/playbook/pb_section_separator/_section_separator.tsx +3 -1
- data/app/pb_kits/playbook/pb_selectable_card/docs/_selectable_card_default.html.erb +2 -1
- data/app/pb_kits/playbook/pb_table/_table.tsx +109 -25
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.html.erb +95 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.jsx +87 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_react.md +2 -0
- data/app/pb_kits/playbook/pb_table/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_table/index.ts +100 -26
- data/app/pb_kits/playbook/pb_table/styles/_all.scss +2 -0
- data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +4 -0
- data/app/pb_kits/playbook/pb_table/styles/_sticky_columns.scss +18 -0
- data/app/pb_kits/playbook/pb_table/table.html.erb +1 -1
- data/app/pb_kits/playbook/pb_table/table.rb +17 -2
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.html.erb +47 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_children.jsx +59 -0
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +3 -0
- data/app/pb_kits/playbook/pb_typeahead/index.ts +29 -3
- data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +5 -2
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +4 -0
- data/app/pb_kits/playbook/tokens/_height.scss +19 -0
- data/app/pb_kits/playbook/tokens/exports/_height.module.scss +37 -0
- data/app/pb_kits/playbook/utilities/_height.scss +33 -0
- data/app/pb_kits/playbook/utilities/_max_width.scss +29 -9
- data/app/pb_kits/playbook/utilities/_min_width.scss +6 -2
- data/app/pb_kits/playbook/utilities/_width.scss +45 -0
- data/app/pb_kits/playbook/utilities/globalPropNames.mjs +1 -1
- data/app/pb_kits/playbook/utilities/globalProps.ts +37 -4
- data/dist/chunks/_typeahead-CCDoUmRR.js +22 -0
- data/dist/chunks/_weekday_stacked-CxjKLoMr.js +45 -0
- data/dist/chunks/{lib-BC6ESsxG.js → lib-CVPInSs5.js} +2 -2
- data/dist/chunks/{pb_form_validation-B_Z9rEbg.js → pb_form_validation-CDLJ5eAG.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +321 -0
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/classnames.rb +4 -0
- data/lib/playbook/forms/builder/typeahead_field.rb +13 -0
- data/lib/playbook/height.rb +29 -0
- data/lib/playbook/kit_base.rb +16 -1
- data/lib/playbook/max_height.rb +29 -0
- data/lib/playbook/min_height.rb +29 -0
- data/lib/playbook/spacing.rb +21 -0
- data/lib/playbook/version.rb +2 -2
- metadata +32 -9
- data/dist/chunks/_typeahead-D0PihN_3.js +0 -22
- data/dist/chunks/_weekday_stacked-uMIX8f-A.js +0 -45
@@ -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)
|
@@ -17,3 +18,5 @@ examples:
|
|
17
18
|
- advanced_table_inline_row_loading: Inline Row Loading
|
18
19
|
- advanced_table_responsive: Responsive Tables
|
19
20
|
- advanced_table_custom_cell: Custom Components for Cells
|
21
|
+
- advanced_table_pagination: Pagination
|
22
|
+
- advanced_table_pagination_with_props: Pagination Props
|
@@ -10,3 +10,5 @@ export { default as AdvancedTableTableProps } from './_advanced_table_table_prop
|
|
10
10
|
export { default as AdvancedTableInlineRowLoading } from './_advanced_table_inline_row_loading.jsx'
|
11
11
|
export { default as AdvancedTableResponsive } from './_advanced_table_responsive.jsx'
|
12
12
|
export { default as AdvancedTableCustomCell } from './_advanced_table_custom_cell.jsx'
|
13
|
+
export { default as AdvancedTablePagination } from './_advanced_table_pagination.jsx'
|
14
|
+
export { default as AdvancedTablePaginationWithProps } from './_advanced_table_pagination_with_props.jsx'
|
@@ -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
|
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={
|
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
|
-
|
2
|
-
|
3
|
-
|
4
|
-
name:
|
5
|
-
|
6
|
-
|
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
|
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:
|
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
|
+
})
|
@@ -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'
|