playbook_ui 14.5.0 → 14.6.0.pre.alpha.PBNTR5554217
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/pb_advanced_table/_advanced_table.tsx +25 -7
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell.jsx +72 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell.md +5 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/index.js +60 -0
- data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +1 -9
- data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.html.erb +1 -9
- data/app/pb_kits/playbook/pb_card/_card.tsx +5 -1
- data/app/pb_kits/playbook/pb_currency/_currency.tsx +16 -6
- data/app/pb_kits/playbook/pb_currency/currency.rb +38 -11
- data/app/pb_kits/playbook/pb_currency/currency.test.js +35 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.html.erb +7 -0
- data/app/pb_kits/playbook/pb_currency/docs/_currency_comma_separator.jsx +18 -0
- data/app/pb_kits/playbook/pb_currency/docs/example.yml +3 -1
- data/app/pb_kits/playbook/pb_currency/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +5 -1
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.html.erb +30 -7
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.md +0 -2
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +84 -3
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +28 -5
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.jsx +45 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.html.erb +9 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.jsx +33 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.html.erb +10 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.jsx +34 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +5 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/index.js +3 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +10 -1
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +1 -1
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +2 -2
- data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.tsx +2 -0
- data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +2 -0
- data/app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.tsx +4 -1
- data/app/pb_kits/playbook/pb_filter/Filter/ResultsCount.tsx +4 -2
- data/app/pb_kits/playbook/pb_filter/docs/_filter_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props.html.erb +41 -0
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props.jsx +71 -0
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props_rails.md +1 -0
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props_react.md +1 -0
- data/app/pb_kits/playbook/pb_filter/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_filter/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_filter/filter.html.erb +2 -2
- data/app/pb_kits/playbook/pb_filter/filter.rb +2 -0
- data/app/pb_kits/playbook/pb_flex/_flex.tsx +3 -1
- data/app/pb_kits/playbook/pb_flex/_flex_item.tsx +8 -2
- data/app/pb_kits/playbook/pb_flex/flex_item.html.erb +3 -6
- data/app/pb_kits/playbook/pb_flex/flex_item.rb +7 -2
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.html.erb +39 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.md +1 -0
- data/app/pb_kits/playbook/pb_form/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_form/form.rb +2 -0
- data/app/pb_kits/playbook/pb_form/formHelper.js +27 -0
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +9 -1
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.html.erb +19 -0
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.jsx +27 -0
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.md +1 -0
- data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_form_pill/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +211 -227
- data/app/pb_kits/playbook/pb_multi_level_select/context/index.tsx +5 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.html.erb +93 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.md +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +105 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.md +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +106 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.md +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select_options.tsx +149 -0
- data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.scss +169 -65
- data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.test.js +5 -5
- data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.tsx +15 -9
- data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_multiple_users_stacked_size.html.erb +336 -0
- data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_multiple_users_stacked_size.jsx +97 -0
- data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_multiple_users_stacked/multiple_users_stacked.html.erb +28 -6
- data/app/pb_kits/playbook/pb_multiple_users_stacked/multiple_users_stacked.rb +31 -1
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +86 -18
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +15 -6
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.md +1 -1
- data/app/pb_kits/playbook/pb_phone_number_input/intlTelInput.scss +849 -931
- data/app/pb_kits/playbook/pb_phone_number_input/types.d.ts +4 -1
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +6 -2
- data/app/pb_kits/playbook/pb_popover/docs/_popover_default.html.erb +1 -1
- data/app/pb_kits/playbook/pb_popover/popover.rb +3 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +4 -1
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +3 -1
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +3 -1
- data/app/pb_kits/playbook/utilities/globalPropNames.mjs +3 -0
- data/app/pb_kits/playbook/utilities/globalProps.ts +39 -2
- data/dist/chunks/_typeahead-BhHnXJjy.js +22 -0
- data/dist/chunks/_weekday_stacked-C2icYweq.js +45 -0
- data/dist/chunks/{lib-CEpcaI8y.js → lib-D-mTv-kp.js} +1 -1
- data/dist/chunks/{pb_form_validation-D9zkwt2b.js → pb_form_validation-BkWGwJsl.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- 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/kit_base.rb +21 -1
- data/lib/playbook/pb_doc_helper.rb +5 -5
- data/lib/playbook/pb_forms_helper.rb +3 -1
- data/lib/playbook/version.rb +2 -2
- metadata +40 -9
- data/dist/chunks/_typeahead-BYw0HEgO.js +0 -22
- data/dist/chunks/_weekday_stacked-DumiyWjh.js +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 386f151fd01fd07dd00e2bbb98f290eb5a2d1d71fd775da6cbe748fb2967aa5c
|
4
|
+
data.tar.gz: 1b1af709f31c4e02bfa5b88bcfa9ad3bd97f8e59ebe000219030cd754d0bdfdd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c4dba5e3cd240d2e97629214ee5c9c592be48a507d3584e0f0bcb109e182c0434437c4d2e31059bfa4fcb68762b0fe41ffd32b6aceb2bc7d57b9b11314a8b10
|
7
|
+
data.tar.gz: 7b69c72fb69a6367826cef4b40304f4fee9df732b3ea2290f25b44ddac687c741c618ab9b628040d96f8642079ae6cd87495bf50a19963a241b032b60cabbfeb
|
@@ -91,7 +91,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
|
|
91
91
|
const columnHelper = createColumnHelper()
|
92
92
|
|
93
93
|
//Create cells for first columns
|
94
|
-
const createCellFunction = (cellAccessors: string[]) => {
|
94
|
+
const createCellFunction = (cellAccessors: string[], customRenderer?: (row: Row<GenericObject>, value: any) => JSX.Element) => {
|
95
95
|
const columnCells = ({
|
96
96
|
row,
|
97
97
|
getValue,
|
@@ -101,6 +101,11 @@ const AdvancedTable = (props: AdvancedTableProps) => {
|
|
101
101
|
}) => {
|
102
102
|
const rowData = row.original
|
103
103
|
|
104
|
+
// Use customRenderer if provided, otherwise default rendering
|
105
|
+
if (customRenderer) {
|
106
|
+
return customRenderer(row, getValue())
|
107
|
+
}
|
108
|
+
|
104
109
|
switch (row.depth) {
|
105
110
|
case 0: {
|
106
111
|
return (
|
@@ -134,18 +139,31 @@ const AdvancedTable = (props: AdvancedTableProps) => {
|
|
134
139
|
//Create column array in format needed by Tanstack
|
135
140
|
const columns =
|
136
141
|
columnDefinitions &&
|
137
|
-
columnDefinitions.map((column) => {
|
142
|
+
columnDefinitions.map((column, index) => {
|
138
143
|
// Define the base column structure
|
139
144
|
const columnStructure = {
|
140
145
|
...columnHelper.accessor(column.accessor, {
|
141
146
|
header: column.label,
|
142
147
|
}),
|
143
148
|
}
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
+
|
150
|
+
// Use the custom renderer if provided, EXCEPT for the first column
|
151
|
+
if (index !== 0) {
|
152
|
+
if (column.cellAccessors || column.customRenderer) {
|
153
|
+
columnStructure.cell = createCellFunction(
|
154
|
+
column.cellAccessors,
|
155
|
+
column.customRenderer
|
156
|
+
)
|
157
|
+
}
|
158
|
+
} else {
|
159
|
+
// For the first column, apply createCellFunction without customRenderer
|
160
|
+
if (column.cellAccessors) {
|
161
|
+
columnStructure.cell = createCellFunction(column.cellAccessors)
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
return columnStructure
|
166
|
+
})
|
149
167
|
|
150
168
|
//Syntax for sorting Array if we want to manage state ourselves
|
151
169
|
const sorting = [
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import React from "react"
|
2
|
+
import { AdvancedTable, Pill, Body, Flex, Detail, Caption } from "playbook-ui"
|
3
|
+
import MOCK_DATA from "./advanced_table_mock_data.json"
|
4
|
+
|
5
|
+
const AdvancedTableCustomCell = (props) => {
|
6
|
+
const columnDefinitions = [
|
7
|
+
{
|
8
|
+
accessor: "year",
|
9
|
+
label: "Year",
|
10
|
+
cellAccessors: ["quarter", "month", "day"],
|
11
|
+
|
12
|
+
},
|
13
|
+
{
|
14
|
+
accessor: "newEnrollments",
|
15
|
+
label: "New Enrollments",
|
16
|
+
customRenderer: (row, value) => (
|
17
|
+
<Pill text={value}
|
18
|
+
variant="success"
|
19
|
+
/>
|
20
|
+
),
|
21
|
+
},
|
22
|
+
{
|
23
|
+
accessor: "scheduledMeetings",
|
24
|
+
label: "Scheduled Meetings",
|
25
|
+
customRenderer: (row, value) => <Body><a href="#">{value}</a></Body>,
|
26
|
+
},
|
27
|
+
{
|
28
|
+
accessor: "attendanceRate",
|
29
|
+
label: "Attendance Rate",
|
30
|
+
customRenderer: (row, value) => (
|
31
|
+
<Flex alignItems="end"
|
32
|
+
orientation="column"
|
33
|
+
>
|
34
|
+
<Detail bold
|
35
|
+
color="default"
|
36
|
+
text={value}
|
37
|
+
/>
|
38
|
+
<Caption size="xs">{row.original.graduatedStudents}</Caption>
|
39
|
+
</Flex>
|
40
|
+
),
|
41
|
+
},
|
42
|
+
{
|
43
|
+
accessor: "completedClasses",
|
44
|
+
label: "Completed Classes",
|
45
|
+
},
|
46
|
+
{
|
47
|
+
accessor: "classCompletionRate",
|
48
|
+
label: "Class Completion Rate",
|
49
|
+
},
|
50
|
+
{
|
51
|
+
accessor: "graduatedStudents",
|
52
|
+
label: "Graduated Students",
|
53
|
+
},
|
54
|
+
]
|
55
|
+
|
56
|
+
return (
|
57
|
+
<div>
|
58
|
+
<AdvancedTable
|
59
|
+
columnDefinitions={columnDefinitions}
|
60
|
+
enableToggleExpansion="all"
|
61
|
+
responsive="none"
|
62
|
+
tableData={MOCK_DATA}
|
63
|
+
{...props}
|
64
|
+
>
|
65
|
+
<AdvancedTable.Header enableSorting />
|
66
|
+
<AdvancedTable.Body />
|
67
|
+
</AdvancedTable>
|
68
|
+
</div>
|
69
|
+
)
|
70
|
+
}
|
71
|
+
|
72
|
+
export default AdvancedTableCustomCell
|
@@ -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 `customRenderer` item within each columnDefinition. 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. To access the data, use `row.original` which is the entire data object for the current row. See the code snippet below for 3 separate use cases and how they were acheived.
|
2
|
+
|
3
|
+
See [here](https://playbook.powerapp.cloud/kits/advanced_table/react#columnDefinitions) for more indepth information on columnDefinitions 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 tableData 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
|
+
|
6
7
|
react:
|
7
8
|
- advanced_table_default: Default (Required Props)
|
8
9
|
- advanced_table_loading: Loading State
|
@@ -15,3 +16,4 @@ examples:
|
|
15
16
|
- advanced_table_table_props: Table Props
|
16
17
|
- advanced_table_inline_row_loading: Inline Row Loading
|
17
18
|
- advanced_table_responsive: Responsive Tables
|
19
|
+
- advanced_table_custom_cell: Custom Components for Cells
|
@@ -9,3 +9,4 @@ export { default as AdvancedTableTableOptions } from './_advanced_table_table_op
|
|
9
9
|
export { default as AdvancedTableTableProps } from './_advanced_table_table_props.jsx'
|
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
|
+
export { default as AdvancedTableCustomCell } from './_advanced_table_custom_cell.jsx'
|
@@ -13,9 +13,20 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
13
13
|
get target() {
|
14
14
|
return document.querySelector(CONTENT_SELECTOR.replace("id", this.element.id))
|
15
15
|
}
|
16
|
+
|
17
|
+
static expandedRows = new Set()
|
18
|
+
static isCollapsing = false
|
16
19
|
|
17
20
|
connect() {
|
18
21
|
this.element.addEventListener('click', () => {
|
22
|
+
if (!PbAdvancedTable.isCollapsing) {
|
23
|
+
const isExpanded = this.element.querySelector(UP_ARROW_SELECTOR).style.display === 'inline-block'
|
24
|
+
if (!isExpanded) {
|
25
|
+
PbAdvancedTable.expandedRows.add(this.element.id)
|
26
|
+
} else {
|
27
|
+
PbAdvancedTable.expandedRows.delete(this.element.id)
|
28
|
+
}
|
29
|
+
}
|
19
30
|
this.toggleElement(this.target)
|
20
31
|
})
|
21
32
|
}
|
@@ -75,4 +86,53 @@ export default class PbAdvancedTable extends PbEnhancedElement {
|
|
75
86
|
this.element.querySelector(UP_ARROW_SELECTOR).style.display = 'inline-block'
|
76
87
|
this.element.querySelector(DOWN_ARROW_SELECTOR).style.display = 'none'
|
77
88
|
}
|
89
|
+
|
90
|
+
static handleToggleAllHeaders(element) {
|
91
|
+
const table = element.closest('.pb_table')
|
92
|
+
const firstLevelButtons = table.querySelectorAll('.pb_advanced_table_body > .pb_table_tr [data-advanced-table]')
|
93
|
+
|
94
|
+
const expandedRows = Array.from(firstLevelButtons).filter(button =>
|
95
|
+
button.querySelector(UP_ARROW_SELECTOR).style.display === 'inline-block'
|
96
|
+
)
|
97
|
+
|
98
|
+
if (expandedRows.length === firstLevelButtons.length) {
|
99
|
+
expandedRows.forEach(button => {
|
100
|
+
button.click()
|
101
|
+
})
|
102
|
+
this.expandedRows.clear()
|
103
|
+
} else {
|
104
|
+
firstLevelButtons.forEach(button => {
|
105
|
+
if (!this.expandedRows.has(button.id)) {
|
106
|
+
button.click()
|
107
|
+
}
|
108
|
+
})
|
109
|
+
}
|
110
|
+
}
|
111
|
+
static handleToggleAllSubRows(element, rowDepth) {
|
112
|
+
const parentElement = element.closest(".toggle-content")
|
113
|
+
const subrowButtons = parentElement.querySelectorAll('.depth-sub-row-' + rowDepth + ' [data-advanced-table]')
|
114
|
+
|
115
|
+
const expandedSubRows = Array.from(subrowButtons).filter(button =>
|
116
|
+
button.querySelector(UP_ARROW_SELECTOR).style.display === 'inline-block'
|
117
|
+
)
|
118
|
+
|
119
|
+
if (expandedSubRows.length === subrowButtons.length) {
|
120
|
+
expandedSubRows.forEach(button => {
|
121
|
+
button.click()
|
122
|
+
})
|
123
|
+
} else {
|
124
|
+
subrowButtons.forEach(button => {
|
125
|
+
if (!this.expandedRows.has(button.id)) {
|
126
|
+
button.click()
|
127
|
+
}
|
128
|
+
})
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
window.expandAllRows = (element) => {
|
134
|
+
PbAdvancedTable.handleToggleAllHeaders(element)
|
78
135
|
}
|
136
|
+
window.expandAllSubRows = (element, rowDepth) => {
|
137
|
+
PbAdvancedTable.handleToggleAllSubRows(element, rowDepth)
|
138
|
+
}
|
@@ -13,12 +13,4 @@
|
|
13
13
|
<% end %>
|
14
14
|
<% end %>
|
15
15
|
<% end %>
|
16
|
-
<% end %>
|
17
|
-
|
18
|
-
<script type="text/javascript">
|
19
|
-
var expandAllRows = (element) => {
|
20
|
-
element.closest('.pb_table').querySelectorAll('.pb_advanced_table_body > .pb_table_tr [data-advanced-table]').forEach((button) => {
|
21
|
-
button.dispatchEvent(new Event('click'));
|
22
|
-
});
|
23
|
-
};
|
24
|
-
</script>
|
16
|
+
<% end %>
|
@@ -23,12 +23,4 @@
|
|
23
23
|
<% end %>
|
24
24
|
<% end %>
|
25
25
|
<% end %>
|
26
|
-
<% end %>
|
27
|
-
|
28
|
-
<script type="text/javascript">
|
29
|
-
var expandAllSubRows = (element, rowDepth) => {
|
30
|
-
element.closest(".toggle-content").querySelectorAll('.depth-sub-row-' + rowDepth + ' [data-advanced-table]').forEach((button) => {
|
31
|
-
button.dispatchEvent(new Event('click'));
|
32
|
-
});
|
33
|
-
};
|
34
|
-
</script>
|
26
|
+
<% end %>
|
@@ -5,7 +5,7 @@ import { get } from 'lodash'
|
|
5
5
|
import classnames from 'classnames'
|
6
6
|
|
7
7
|
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
|
8
|
-
import { GlobalProps, globalProps } from '../utilities/globalProps'
|
8
|
+
import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
|
9
9
|
import type { ProductColors, CategoryColors, BackgroundColors } from '../types/colors'
|
10
10
|
|
11
11
|
import Icon from '../pb_icon/_icon'
|
@@ -49,6 +49,7 @@ type CardBodyProps = {
|
|
49
49
|
padding?: string,
|
50
50
|
} & GlobalProps
|
51
51
|
|
52
|
+
|
52
53
|
// Header component
|
53
54
|
const Header = (props: CardHeaderProps) => {
|
54
55
|
const { children, className, headerColor = 'category_1', headerColorStriped = false } = props
|
@@ -107,6 +108,7 @@ const Card = (props: CardPropTypes): React.ReactElement => {
|
|
107
108
|
|
108
109
|
// coerce to array
|
109
110
|
const cardChildren = React.Children.toArray(children)
|
111
|
+
const dynamicInlineProps = globalInlineProps(props);
|
110
112
|
|
111
113
|
const subComponentTags = (tagName: string) => {
|
112
114
|
return cardChildren.filter((c: string) => (
|
@@ -135,6 +137,7 @@ const Card = (props: CardPropTypes): React.ReactElement => {
|
|
135
137
|
{...dataProps}
|
136
138
|
{...htmlProps}
|
137
139
|
className={classnames(cardCss, globalProps(props), className)}
|
140
|
+
style={dynamicInlineProps}
|
138
141
|
>
|
139
142
|
{subComponentTags('Header')}
|
140
143
|
{
|
@@ -163,6 +166,7 @@ const Card = (props: CardPropTypes): React.ReactElement => {
|
|
163
166
|
{...dataProps}
|
164
167
|
{...htmlProps}
|
165
168
|
className={classnames(cardCss, globalProps(props), className)}
|
169
|
+
style={dynamicInlineProps}
|
166
170
|
>
|
167
171
|
{subComponentTags('Header')}
|
168
172
|
{nonHeaderChildren}
|
@@ -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
|
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
|
-
|
93
|
+
const getMatchingDecimalAmount = decimals === "matching" ? amount : whole
|
94
|
+
const getMatchingDecimalValue = decimals === "matching" ? '' : `.${decimal}`
|
93
95
|
|
94
|
-
const
|
95
|
-
|
96
|
-
|
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 :
|
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
|
-
|
100
|
-
|
101
|
-
|
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
|
105
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
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
|
+
comma_separator
|
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
|
+
comma_separator
|
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
|
+
comma_separator
|
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,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
|
@@ -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'
|
@@ -6,7 +6,7 @@ import classnames from "classnames";
|
|
6
6
|
import Modal from "react-modal";
|
7
7
|
|
8
8
|
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
|
9
|
-
import { globalProps } from "../utilities/globalProps";
|
9
|
+
import { globalProps, globalInlineProps } from "../utilities/globalProps";
|
10
10
|
|
11
11
|
import Body from "../pb_body/_body";
|
12
12
|
import Button from "../pb_button/_button";
|
@@ -91,6 +91,8 @@ const Dialog = (props: DialogProps): React.ReactElement => {
|
|
91
91
|
beforeClose: "pb_dialog_overlay_before_close",
|
92
92
|
};
|
93
93
|
|
94
|
+
const dynamicInlineProps = globalInlineProps(props);
|
95
|
+
|
94
96
|
const classes = classnames(
|
95
97
|
buildCss("pb_dialog_wrapper"),
|
96
98
|
globalProps(props),
|
@@ -184,6 +186,7 @@ const Dialog = (props: DialogProps): React.ReactElement => {
|
|
184
186
|
overlayClassName={overlayClassNames}
|
185
187
|
portalClassName={portalClassName}
|
186
188
|
shouldCloseOnOverlayClick={shouldCloseOnOverlayClick && !loading}
|
189
|
+
style={{ content: dynamicInlineProps }}
|
187
190
|
>
|
188
191
|
<>
|
189
192
|
{title && !status ? <Dialog.Header>{title}</Dialog.Header> : null}
|
@@ -192,6 +195,7 @@ const Dialog = (props: DialogProps): React.ReactElement => {
|
|
192
195
|
<Dialog.Body
|
193
196
|
className="dialog_status_text_align"
|
194
197
|
padding="md"
|
198
|
+
|
195
199
|
>
|
196
200
|
<Flex align="center"
|
197
201
|
orientation="column"
|
@@ -1,13 +1,36 @@
|
|
1
1
|
<%= pb_rails("button", props: { text: "Open Dialog", data: {"open-dialog": "dialog-loading"} }) %>
|
2
2
|
|
3
|
-
<%= pb_rails("dialog", props: {
|
4
|
-
id:"dialog-loading",
|
5
|
-
size: "sm",
|
6
|
-
title: "Loading
|
7
|
-
text: "Make a loading request?",
|
8
|
-
cancel_button: "Cancel Button",
|
3
|
+
<%= pb_rails("dialog", props: {
|
4
|
+
id:"dialog-loading",
|
5
|
+
size: "sm",
|
6
|
+
title: "Loading Example",
|
7
|
+
text: "Make a loading request?",
|
8
|
+
cancel_button: "Cancel Button",
|
9
9
|
cancel_button_id: "cancel-button-loading",
|
10
|
-
confirm_button: "Okay",
|
10
|
+
confirm_button: "Okay",
|
11
11
|
confirm_button_id: "confirm-button-loading",
|
12
12
|
loading: true,
|
13
13
|
}) %>
|
14
|
+
|
15
|
+
<script>
|
16
|
+
const loadingButton = document.querySelector('[data-disable-with="Loading"]');
|
17
|
+
if (loadingButton) {
|
18
|
+
loadingButton.addEventListener("click", function() {
|
19
|
+
const okayLoadingButton = document.querySelector('[data-disable-with="Loading"]');
|
20
|
+
const cancelButton = document.querySelector('[data-disable-cancel-with="Loading"]');
|
21
|
+
let currentClass = okayLoadingButton.className;
|
22
|
+
let cancelClass = cancelButton ? cancelButton.className : "";
|
23
|
+
|
24
|
+
setTimeout(function() {
|
25
|
+
okayLoadingButton.disabled = false;
|
26
|
+
okayLoadingButton.className = currentClass.replace("_disabled_loading", "_enabled");
|
27
|
+
|
28
|
+
if (cancelButton) {
|
29
|
+
cancelButton.disabled = false;
|
30
|
+
cancelButton.className = cancelClass.replace("_disabled", "_enabled");
|
31
|
+
}
|
32
|
+
}, 5000);
|
33
|
+
|
34
|
+
});
|
35
|
+
}
|
36
|
+
</script>
|