playbook_ui 14.5.0 → 14.6.0.pre.alpha.PBNTR5554217
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 +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>
|