playbook_ui 16.7.0.pre.rc.0 → 16.7.0.pre.rc.1
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/docs/_advanced_table_grouped_headers_composition.jsx +15 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +2 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_inline_row_loading.jsx +2 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +2 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_inline_loading_empty_children.json +41 -0
- data/app/pb_kits/playbook/pb_bread_crumbs/docs/_bread_crumbs_default.jsx +5 -5
- data/app/pb_kits/playbook/pb_button/_button.scss +1 -2
- data/app/pb_kits/playbook/pb_dialog/index.js +6 -1
- data/app/pb_kits/playbook/pb_draggable/index.js +6 -1
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_external_control.jsx +22 -1
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change.jsx +22 -2
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +68 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_show_placeholder.html.erb +5 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_show_placeholder.jsx +14 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_show_placeholder.md +3 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_phone_number_input/kit.schema.json +8 -0
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +79 -2
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_templates.jsx +76 -1
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_react_hook.jsx +2 -2
- data/dist/chunks/{_typeahead-DO5eU-VL.js → _typeahead-Cl5cZ7Hz.js} +1 -1
- data/dist/chunks/vendor.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/version.rb +1 -1
- metadata +7 -8
- data/app/pb_kits/playbook/pb_advanced_table/docs/_mock_data_inline_loading.js +0 -200
- data/app/pb_kits/playbook/pb_advanced_table/docs/_mock_data_inline_loading_empty_children.js +0 -42
- data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_grouped_headers_composition_mock_data.json +0 -98
- data/app/pb_kits/playbook/pb_pagination/docs/data.js +0 -23
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/templates.js +0 -75
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84a662254cd2533c99982e9c3d92cf898c52aa151e267258ea4a8e5007856b44
|
|
4
|
+
data.tar.gz: ff974535354bd21c7aef9810593b5898968080539f9d7fc673acacffcb96aad0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5bba8f8aa8b742c61dcfdf739552e920fea3c73afb647c904891737a38240c13a598c8a6a3036f73d1d85db56555b3db56bc2b418dbd0cdce2ec5067fb27d25a
|
|
7
|
+
data.tar.gz: 2716f834102e665c6975a1a80db09c6ae84a1b558a74027903f5ce7602f1e5ab2d0f1e6fb481c37199fe6cf6804cb9b79d01de8cd867c8742e071c04bfddb690
|
data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_grouped_headers_composition.jsx
CHANGED
|
@@ -9,7 +9,21 @@ import ListItem from "../../pb_list/_list_item"
|
|
|
9
9
|
import PbReactPopover from "../../pb_popover/_popover"
|
|
10
10
|
import SectionSeparator from "../../pb_section_separator/_section_separator"
|
|
11
11
|
import StarRating from "../../pb_star_rating/_star_rating"
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
const COMPOSITION_MOCK_DATA = [
|
|
14
|
+
{ id: "1", year: "2015", newEnrollments: "12", scheduledMeetings: "40", attendanceRate: "62%", classCompletionRate: "28%" },
|
|
15
|
+
{ id: "2", year: "2016", newEnrollments: "88", scheduledMeetings: "12", attendanceRate: "71%", classCompletionRate: "55%" },
|
|
16
|
+
{ id: "3", year: "2017", newEnrollments: "34", scheduledMeetings: "67", attendanceRate: "58%", classCompletionRate: "41%" },
|
|
17
|
+
{ id: "4", year: "2018", newEnrollments: "05", scheduledMeetings: "91", attendanceRate: "44%", classCompletionRate: "73%" },
|
|
18
|
+
{ id: "5", year: "2019", newEnrollments: "61", scheduledMeetings: "19", attendanceRate: "83%", classCompletionRate: "36%" },
|
|
19
|
+
{ id: "6", year: "2020", newEnrollments: "19", scheduledMeetings: "54", attendanceRate: "67%", classCompletionRate: "62%" },
|
|
20
|
+
{ id: "7", year: "2021", newEnrollments: "73", scheduledMeetings: "08", attendanceRate: "52%", classCompletionRate: "49%" },
|
|
21
|
+
{ id: "8", year: "2022", newEnrollments: "50", scheduledMeetings: "50", attendanceRate: "75%", classCompletionRate: "45%" },
|
|
22
|
+
{ id: "9", year: "2023", newEnrollments: "95", scheduledMeetings: "03", attendanceRate: "69%", classCompletionRate: "81%" },
|
|
23
|
+
{ id: "10", year: "2024", newEnrollments: "27", scheduledMeetings: "76", attendanceRate: "91%", classCompletionRate: "22%" },
|
|
24
|
+
{ id: "11", year: "2025", newEnrollments: "41", scheduledMeetings: "33", attendanceRate: "48%", classCompletionRate: "94%" },
|
|
25
|
+
{ id: "12", year: "2026", newEnrollments: "66", scheduledMeetings: "66", attendanceRate: "55%", classCompletionRate: "58%" },
|
|
26
|
+
]
|
|
13
27
|
|
|
14
28
|
const LEAF_COUNT = "newEnrollments"
|
|
15
29
|
const LEAF_SCHEDULED = "scheduledMeetings"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import AdvancedTable from '../_advanced_table'
|
|
3
|
-
import
|
|
3
|
+
import INFINITE_SCROLL_MOCK_DATA from "./advanced_table_mock_data_infinite_scroll.json"
|
|
4
4
|
|
|
5
5
|
const AdvancedTableInfiniteScroll = (props) => {
|
|
6
6
|
const columnDefinitions = [
|
|
@@ -39,7 +39,7 @@ const AdvancedTableInfiniteScroll = (props) => {
|
|
|
39
39
|
<div>
|
|
40
40
|
<AdvancedTable
|
|
41
41
|
columnDefinitions={columnDefinitions}
|
|
42
|
-
tableData={
|
|
42
|
+
tableData={INFINITE_SCROLL_MOCK_DATA}
|
|
43
43
|
virtualizedRows
|
|
44
44
|
{...props}
|
|
45
45
|
/>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import AdvancedTable from '../../pb_advanced_table/_advanced_table'
|
|
3
3
|
import Caption from '../../pb_caption/_caption'
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import MOCK_DATA_INLINE_LOADING from "./advanced_table_mock_data_inline_loading.json"
|
|
5
|
+
import MOCK_DATA_INLINE_LOADING_EMPTY_CHILDREN from "./advanced_table_mock_data_inline_loading_empty_children.json"
|
|
6
6
|
|
|
7
7
|
const AdvancedTableInlineRowLoading = (props) => {
|
|
8
8
|
const columnDefinitions = [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState } from "react"
|
|
2
2
|
import AdvancedTable from '../_advanced_table'
|
|
3
|
-
import
|
|
3
|
+
import MOCK_DATA_WITH_ID from "./advanced_table_mock_data_with_id.json"
|
|
4
4
|
|
|
5
5
|
const AdvancedTableRowPinning = (props) => {
|
|
6
6
|
const columnDefinitions = [
|
|
@@ -43,7 +43,7 @@ const AdvancedTableRowPinning = (props) => {
|
|
|
43
43
|
columnDefinitions={columnDefinitions}
|
|
44
44
|
maxHeight="xs"
|
|
45
45
|
pinnedRows={{value: pinnedRows, onChange: setPinnedRows}}
|
|
46
|
-
tableData={
|
|
46
|
+
tableData={MOCK_DATA_WITH_ID}
|
|
47
47
|
tableProps={{sticky: true}}
|
|
48
48
|
{...props}
|
|
49
49
|
>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"year": "2021",
|
|
4
|
+
"quarter": null,
|
|
5
|
+
"month": null,
|
|
6
|
+
"day": null,
|
|
7
|
+
"newEnrollments": "20",
|
|
8
|
+
"scheduledMeetings": "10",
|
|
9
|
+
"attendanceRate": "51%",
|
|
10
|
+
"completedClasses": "3",
|
|
11
|
+
"classCompletionRate": "33%",
|
|
12
|
+
"graduatedStudents": "19",
|
|
13
|
+
"children": []
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"year": "2022",
|
|
17
|
+
"quarter": null,
|
|
18
|
+
"month": null,
|
|
19
|
+
"day": null,
|
|
20
|
+
"newEnrollments": "25",
|
|
21
|
+
"scheduledMeetings": "17",
|
|
22
|
+
"attendanceRate": "75%",
|
|
23
|
+
"completedClasses": "5",
|
|
24
|
+
"classCompletionRate": "45%",
|
|
25
|
+
"graduatedStudents": "32",
|
|
26
|
+
"children": []
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"year": "2023",
|
|
30
|
+
"quarter": null,
|
|
31
|
+
"month": null,
|
|
32
|
+
"day": null,
|
|
33
|
+
"newEnrollments": "10",
|
|
34
|
+
"scheduledMeetings": "15",
|
|
35
|
+
"attendanceRate": "65%",
|
|
36
|
+
"completedClasses": "4",
|
|
37
|
+
"classCompletionRate": "49%",
|
|
38
|
+
"graduatedStudents": "29",
|
|
39
|
+
"children": []
|
|
40
|
+
}
|
|
41
|
+
]
|
|
@@ -4,7 +4,7 @@ import Icon from "../../pb_icon/_icon"
|
|
|
4
4
|
import Title from "../../pb_title/_title"
|
|
5
5
|
import BreadCrumbItem from '../_bread_crumb_item'
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const LinkSection = (props) => <BreadCrumbItem {...props} />
|
|
8
8
|
const BreadCrumbsDefault = (props) => {
|
|
9
9
|
return (
|
|
10
10
|
<BreadCrumbs
|
|
@@ -35,7 +35,7 @@ const BreadCrumbsDefault = (props) => {
|
|
|
35
35
|
size="1x"
|
|
36
36
|
{...props}
|
|
37
37
|
/>
|
|
38
|
-
<
|
|
38
|
+
<LinkSection
|
|
39
39
|
{...props}
|
|
40
40
|
href="/users"
|
|
41
41
|
>
|
|
@@ -46,20 +46,20 @@ const BreadCrumbsDefault = (props) => {
|
|
|
46
46
|
text="Users"
|
|
47
47
|
{...props}
|
|
48
48
|
/>
|
|
49
|
-
</
|
|
49
|
+
</LinkSection>
|
|
50
50
|
<Icon
|
|
51
51
|
icon="user"
|
|
52
52
|
size="1x"
|
|
53
53
|
{...props}
|
|
54
54
|
/>
|
|
55
|
-
<
|
|
55
|
+
<LinkSection {...props}>
|
|
56
56
|
<Title
|
|
57
57
|
size="4"
|
|
58
58
|
tag="span"
|
|
59
59
|
text="User"
|
|
60
60
|
{...props}
|
|
61
61
|
/>
|
|
62
|
-
</
|
|
62
|
+
</LinkSection>
|
|
63
63
|
</BreadCrumbs>
|
|
64
64
|
)
|
|
65
65
|
}
|
|
@@ -124,8 +124,7 @@ $pb_button_icon_only_dimensions: (
|
|
|
124
124
|
// Rails: .pb_button_icon_only; React: class or :has(...) when label is empty.
|
|
125
125
|
// Rails uses a truly empty .pb_button_content; React wraps text in a child span (may be empty).
|
|
126
126
|
&.pb_button_icon_only,
|
|
127
|
-
&:has(.pb_button_content:empty)
|
|
128
|
-
&:has(.pb_button_content > span:empty) {
|
|
127
|
+
&:has(.pb_button_content:empty) {
|
|
129
128
|
aspect-ratio: 1;
|
|
130
129
|
box-sizing: border-box;
|
|
131
130
|
$pb_button_icon_only_default: map-get($pb_button_icon_only_dimensions, "md");
|
|
@@ -16,7 +16,12 @@ export default class PbDialog extends PbEnhancedElement {
|
|
|
16
16
|
this.domContentLoadedHandler = () => this.setupDialog()
|
|
17
17
|
this.turboFrameLoadHandler = () => this.setupDialog()
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// If DOM is already loaded, setup immediately; otherwise wait for DOMContentLoaded
|
|
20
|
+
if (document.readyState === "loading") {
|
|
21
|
+
window.addEventListener("DOMContentLoaded", this.domContentLoadedHandler)
|
|
22
|
+
} else {
|
|
23
|
+
this.setupDialog()
|
|
24
|
+
}
|
|
20
25
|
window.addEventListener("turbo:frame-load", this.turboFrameLoadHandler)
|
|
21
26
|
|
|
22
27
|
// Code for custom_event_type setup (can take multiple events in a string separated by commas)
|
|
@@ -22,7 +22,12 @@ export default class PbDraggable extends PbEnhancedElement {
|
|
|
22
22
|
this.dragZoneType = "";
|
|
23
23
|
this.dragZoneColor = "";
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
// If DOM is already loaded, bind immediately; otherwise wait for DOMContentLoaded
|
|
26
|
+
if (document.readyState === "loading") {
|
|
27
|
+
document.addEventListener("DOMContentLoaded", () => this.bindEventListeners());
|
|
28
|
+
} else {
|
|
29
|
+
this.bindEventListeners();
|
|
30
|
+
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
setState(newState) {
|
|
@@ -4,7 +4,28 @@ import Pagination from '../../pb_pagination/_pagination'
|
|
|
4
4
|
import Select from '../../pb_select/_select'
|
|
5
5
|
import Table from '../../pb_table/_table'
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const data = [
|
|
8
|
+
["Value 1", "Value 2", "Value 3", "Value 4", "Value 5"],
|
|
9
|
+
["Value 6", "Value 7", "Value 8", "Value 9", "Value 10"],
|
|
10
|
+
["Value 11", "Value 12", "Value 13", "Value 14", "Value 15"],
|
|
11
|
+
["Value 16", "Value 17", "Value 18", "Value 19", "Value 20"],
|
|
12
|
+
["Value 21", "Value 22", "Value 23", "Value 24", "Value 25"],
|
|
13
|
+
["Value 26", "Value 27", "Value 28", "Value 29", "Value 30"],
|
|
14
|
+
["Value 31", "Value 32", "Value 33", "Value 34", "Value 35"],
|
|
15
|
+
["Value 36", "Value 37", "Value 38", "Value 39", "Value 40"],
|
|
16
|
+
["Value 41", "Value 42", "Value 43", "Value 44", "Value 45"],
|
|
17
|
+
["Value 46", "Value 47", "Value 48", "Value 49", "Value 50"],
|
|
18
|
+
["Value 51", "Value 52", "Value 53", "Value 54", "Value 55"],
|
|
19
|
+
["Value 56", "Value 57", "Value 58", "Value 59", "Value 60"],
|
|
20
|
+
["Value 61", "Value 62", "Value 63", "Value 64", "Value 65"],
|
|
21
|
+
["Value 66", "Value 67", "Value 68", "Value 69", "Value 70"],
|
|
22
|
+
["Value 71", "Value 72", "Value 73", "Value 74", "Value 75"],
|
|
23
|
+
["Value 76", "Value 77", "Value 78", "Value 79", "Value 80"],
|
|
24
|
+
["Value 81", "Value 82", "Value 83", "Value 84", "Value 85"],
|
|
25
|
+
["Value 86", "Value 87", "Value 88", "Value 89", "Value 90"],
|
|
26
|
+
["Value 91", "Value 92", "Value 93", "Value 94", "Value 95"],
|
|
27
|
+
["Value 96", "Value 97", "Value 98", "Value 99", "Value 100"],
|
|
28
|
+
];
|
|
8
29
|
|
|
9
30
|
const PaginationExternalControl = (props) => {
|
|
10
31
|
const [totalItems, setTotalItems] = useState(20);
|
|
@@ -2,8 +2,28 @@ import React, { useState } from "react";
|
|
|
2
2
|
import Table from '../../pb_table/_table'
|
|
3
3
|
import Pagination from '../../pb_pagination/_pagination'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const data = [
|
|
6
|
+
["Value 1", "Value 2", "Value 3", "Value 4", "Value 5"],
|
|
7
|
+
["Value 6", "Value 7", "Value 8", "Value 9", "Value 10"],
|
|
8
|
+
["Value 11", "Value 12", "Value 13", "Value 14", "Value 15"],
|
|
9
|
+
["Value 16", "Value 17", "Value 18", "Value 19", "Value 20"],
|
|
10
|
+
["Value 21", "Value 22", "Value 23", "Value 24", "Value 25"],
|
|
11
|
+
["Value 26", "Value 27", "Value 28", "Value 29", "Value 30"],
|
|
12
|
+
["Value 31", "Value 32", "Value 33", "Value 34", "Value 35"],
|
|
13
|
+
["Value 36", "Value 37", "Value 38", "Value 39", "Value 40"],
|
|
14
|
+
["Value 41", "Value 42", "Value 43", "Value 44", "Value 45"],
|
|
15
|
+
["Value 46", "Value 47", "Value 48", "Value 49", "Value 50"],
|
|
16
|
+
["Value 51", "Value 52", "Value 53", "Value 54", "Value 55"],
|
|
17
|
+
["Value 56", "Value 57", "Value 58", "Value 59", "Value 60"],
|
|
18
|
+
["Value 61", "Value 62", "Value 63", "Value 64", "Value 65"],
|
|
19
|
+
["Value 66", "Value 67", "Value 68", "Value 69", "Value 70"],
|
|
20
|
+
["Value 71", "Value 72", "Value 73", "Value 74", "Value 75"],
|
|
21
|
+
["Value 76", "Value 77", "Value 78", "Value 79", "Value 80"],
|
|
22
|
+
["Value 81", "Value 82", "Value 83", "Value 84", "Value 85"],
|
|
23
|
+
["Value 86", "Value 87", "Value 88", "Value 89", "Value 90"],
|
|
24
|
+
["Value 91", "Value 92", "Value 93", "Value 94", "Value 95"],
|
|
25
|
+
["Value 96", "Value 97", "Value 98", "Value 99", "Value 100"],
|
|
26
|
+
];
|
|
7
27
|
|
|
8
28
|
const PaginationPageChange = (props) => {
|
|
9
29
|
|
|
@@ -41,6 +41,7 @@ type PhoneNumberInputProps = {
|
|
|
41
41
|
formatAsYouType?: boolean,
|
|
42
42
|
strictMode?: boolean,
|
|
43
43
|
countrySearch?: boolean,
|
|
44
|
+
showPlaceholder?: boolean,
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
enum ValidationError {
|
|
@@ -98,8 +99,14 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
98
99
|
formatAsYouType = false,
|
|
99
100
|
strictMode = false,
|
|
100
101
|
countrySearch = false,
|
|
102
|
+
showPlaceholder = false,
|
|
101
103
|
} = props
|
|
102
104
|
|
|
105
|
+
const showPlaceholderRef = useRef(showPlaceholder)
|
|
106
|
+
showPlaceholderRef.current = showPlaceholder
|
|
107
|
+
|
|
108
|
+
const placeholderTemplateRef = useRef<string | null>(null)
|
|
109
|
+
|
|
103
110
|
const ariaProps = buildAriaProps(aria)
|
|
104
111
|
const dataProps = buildDataProps(data)
|
|
105
112
|
const htmlProps = buildHtmlProps(htmlOptions)
|
|
@@ -186,6 +193,37 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
186
193
|
return formattedNumber.replace(/\D/g, "")
|
|
187
194
|
}
|
|
188
195
|
|
|
196
|
+
const readInputPlaceholder = (element: HTMLInputElement) => {
|
|
197
|
+
return element.getAttribute("placeholder") || element.placeholder || ""
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const cachePlaceholderTemplate = (element: HTMLInputElement) => {
|
|
201
|
+
const placeholder = readInputPlaceholder(element)
|
|
202
|
+
if (placeholder) {
|
|
203
|
+
placeholderTemplateRef.current = placeholder
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const hidePlaceholderIfFocusedAndEmpty = (element: HTMLInputElement) => {
|
|
208
|
+
if (document.activeElement === element && !element.value) {
|
|
209
|
+
element.setAttribute("placeholder", "")
|
|
210
|
+
return true
|
|
211
|
+
}
|
|
212
|
+
return false
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const hidePlaceholderIfEmpty = (element: HTMLInputElement) => {
|
|
216
|
+
if (!element.value) {
|
|
217
|
+
element.setAttribute("placeholder", "")
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const restorePlaceholderIfEmpty = (element: HTMLInputElement) => {
|
|
222
|
+
if (!element.value && placeholderTemplateRef.current) {
|
|
223
|
+
element.setAttribute("placeholder", placeholderTemplateRef.current)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
189
227
|
const showFormattedError = (reason = '') => {
|
|
190
228
|
const countryName = itiRef.current.getSelectedCountryData().name
|
|
191
229
|
const reasonText = reason.length > 0 ? ` (${reason})` : ''
|
|
@@ -476,6 +514,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
476
514
|
countryOrder: preferredCountries,
|
|
477
515
|
allowDropdown: !disabled,
|
|
478
516
|
autoInsertDialCode: false,
|
|
517
|
+
autoPlaceholder: showPlaceholderRef.current ? "polite" : "off",
|
|
479
518
|
initialCountry: initialCountry || fallbackCountry,
|
|
480
519
|
onlyCountries,
|
|
481
520
|
excludeCountries,
|
|
@@ -497,6 +536,22 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
497
536
|
setSelectedData(phoneNumberData)
|
|
498
537
|
onChange(phoneNumberData)
|
|
499
538
|
validateErrors()
|
|
539
|
+
|
|
540
|
+
if (showPlaceholderRef.current) {
|
|
541
|
+
const syncPlaceholderState = () => {
|
|
542
|
+
const el = inputRef.current
|
|
543
|
+
if (!el) return
|
|
544
|
+
|
|
545
|
+
cachePlaceholderTemplate(el)
|
|
546
|
+
if (hidePlaceholderIfFocusedAndEmpty(el)) return
|
|
547
|
+
restorePlaceholderIfEmpty(el)
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Run immediately, then once on the next tick in case intl-tel-input
|
|
551
|
+
// updates the placeholder asynchronously after countrychange.
|
|
552
|
+
syncPlaceholderState()
|
|
553
|
+
setTimeout(syncPlaceholderState, 0)
|
|
554
|
+
}
|
|
500
555
|
})
|
|
501
556
|
|
|
502
557
|
inputRef.current.addEventListener("open:countrydropdown", () => setDropDownIsOpen(true))
|
|
@@ -538,7 +593,20 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
538
593
|
id,
|
|
539
594
|
label,
|
|
540
595
|
name,
|
|
596
|
+
onFocus: () => {
|
|
597
|
+
if (!showPlaceholder) return
|
|
598
|
+
const el = inputRef.current
|
|
599
|
+
if (!el || el.value) return
|
|
600
|
+
cachePlaceholderTemplate(el)
|
|
601
|
+
hidePlaceholderIfEmpty(el)
|
|
602
|
+
},
|
|
541
603
|
onBlur: () => {
|
|
604
|
+
if (showPlaceholder) {
|
|
605
|
+
const el = inputRef.current
|
|
606
|
+
if (el && !el.value) {
|
|
607
|
+
restorePlaceholderIfEmpty(el)
|
|
608
|
+
}
|
|
609
|
+
}
|
|
542
610
|
hasBlurredRef.current = true
|
|
543
611
|
setHasBlurred(true)
|
|
544
612
|
validateErrors()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PhoneNumberInput from '../../pb_phone_number_input/_phone_number_input'
|
|
3
|
+
|
|
4
|
+
const PhoneNumberInputShowPlaceholder = (props) => (
|
|
5
|
+
<>
|
|
6
|
+
<PhoneNumberInput
|
|
7
|
+
id='phone_number_input_show_placeholder'
|
|
8
|
+
label='Phone Number'
|
|
9
|
+
showPlaceholder
|
|
10
|
+
{...props} />
|
|
11
|
+
</>
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
export default PhoneNumberInputShowPlaceholder
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
The `showPlaceholder`/`show_placeholder` prop enables the country-specific example placeholder in the phone input.
|
|
2
|
+
|
|
3
|
+
By default, the Phone Number Input does not show a placeholder. When enabled, the placeholder appears while the field is empty and unfocused, hides on focus, and returns on blur if no value is entered.
|
|
@@ -2,6 +2,7 @@ examples:
|
|
|
2
2
|
|
|
3
3
|
react:
|
|
4
4
|
- phone_number_input_default: Default
|
|
5
|
+
- phone_number_input_show_placeholder: Show Placeholder
|
|
5
6
|
- phone_number_input_preferred_countries: Preferred Countries
|
|
6
7
|
- phone_number_input_initial_country: Initial Country
|
|
7
8
|
- phone_number_input_only_countries: Only Countries
|
|
@@ -16,6 +17,7 @@ examples:
|
|
|
16
17
|
|
|
17
18
|
rails:
|
|
18
19
|
- phone_number_input_default: Default
|
|
20
|
+
- phone_number_input_show_placeholder: Show Placeholder
|
|
19
21
|
- phone_number_input_preferred_countries: Preferred Countries
|
|
20
22
|
- phone_number_input_initial_country: Initial Country
|
|
21
23
|
- phone_number_input_only_countries: Only Countries
|
|
@@ -10,3 +10,4 @@ export { default as PhoneNumberInputFormat } from './_phone_number_input_format'
|
|
|
10
10
|
export { default as PhoneNumberInputStrictMode } from './_phone_number_input_strict_mode'
|
|
11
11
|
export { default as PhoneNumberInputCountrySearch } from './_phone_number_input_country_search'
|
|
12
12
|
export { default as PhoneNumberInputRequiredIndicator } from './_phone_number_input_required_indicator.jsx'
|
|
13
|
+
export { default as PhoneNumberInputShowPlaceholder } from './_phone_number_input_show_placeholder'
|
|
@@ -35,6 +35,8 @@ module Playbook
|
|
|
35
35
|
default: false
|
|
36
36
|
prop :country_search, type: Playbook::Props::Boolean,
|
|
37
37
|
default: false
|
|
38
|
+
prop :show_placeholder, type: Playbook::Props::Boolean,
|
|
39
|
+
default: false
|
|
38
40
|
|
|
39
41
|
def classname
|
|
40
42
|
generate_classname("pb_phone_number_input")
|
|
@@ -59,6 +61,7 @@ module Playbook
|
|
|
59
61
|
requiredIndicator: required_indicator,
|
|
60
62
|
value: value,
|
|
61
63
|
countrySearch: country_search,
|
|
64
|
+
showPlaceholder: show_placeholder,
|
|
62
65
|
}
|
|
63
66
|
end
|
|
64
67
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { render, screen, act, within } from "../utilities/test-utils";
|
|
2
|
+
import { render, screen, act, within, waitFor, fireEvent } from "../utilities/test-utils";
|
|
3
3
|
import PhoneNumberInput from "./_phone_number_input";
|
|
4
4
|
|
|
5
5
|
const testId = "phoneNumberInput";
|
|
@@ -188,4 +188,81 @@ test("does not render required indicator asterisk when requiredIndicator is fals
|
|
|
188
188
|
const label = within(kit).getByText(/Phone Number/);
|
|
189
189
|
expect(label).toBeInTheDocument();
|
|
190
190
|
expect(kit).not.toHaveTextContent("*");
|
|
191
|
-
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
test("has no intl-tel example placeholder by default (showPlaceholder false)", async () => {
|
|
194
|
+
const props = {
|
|
195
|
+
id: testId,
|
|
196
|
+
initialCountry: "us",
|
|
197
|
+
};
|
|
198
|
+
render(<PhoneNumberInput {...props} />);
|
|
199
|
+
const input = screen.getByRole("textbox");
|
|
200
|
+
await waitFor(() => {
|
|
201
|
+
expect(input.closest(".iti")).toBeTruthy();
|
|
202
|
+
});
|
|
203
|
+
expect(!input.getAttribute("placeholder") || input.getAttribute("placeholder") === "").toBe(true);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("optionally shows example placeholder when showPlaceholder is true; hides on focus and returns on blur if empty", async () => {
|
|
207
|
+
const props = {
|
|
208
|
+
id: testId,
|
|
209
|
+
initialCountry: "us",
|
|
210
|
+
showPlaceholder: true,
|
|
211
|
+
};
|
|
212
|
+
render(<PhoneNumberInput {...props} />);
|
|
213
|
+
const input = screen.getByRole("textbox");
|
|
214
|
+
|
|
215
|
+
await waitFor(() => {
|
|
216
|
+
expect(input.closest(".iti")).toBeTruthy();
|
|
217
|
+
});
|
|
218
|
+
await waitFor(() => {
|
|
219
|
+
expect((input.getAttribute("placeholder") || "").length).toBeGreaterThan(0);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const whenIdle = input.getAttribute("placeholder");
|
|
223
|
+
|
|
224
|
+
act(() => {
|
|
225
|
+
fireEvent.focus(input);
|
|
226
|
+
});
|
|
227
|
+
expect(input.getAttribute("placeholder") || "").toBe("");
|
|
228
|
+
|
|
229
|
+
act(() => {
|
|
230
|
+
fireEvent.blur(input);
|
|
231
|
+
});
|
|
232
|
+
expect(input.getAttribute("placeholder")).toBe(whenIdle);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test("restores latest placeholder on blur after country change", async () => {
|
|
236
|
+
const props = {
|
|
237
|
+
id: testId,
|
|
238
|
+
initialCountry: "us",
|
|
239
|
+
showPlaceholder: true,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
render(<PhoneNumberInput {...props} />);
|
|
243
|
+
const input = screen.getByRole("textbox");
|
|
244
|
+
|
|
245
|
+
await waitFor(() => {
|
|
246
|
+
expect(input.closest(".iti")).toBeTruthy();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Simulate focus behavior
|
|
250
|
+
act(() => {
|
|
251
|
+
fireEvent.focus(input);
|
|
252
|
+
});
|
|
253
|
+
expect(input.getAttribute("placeholder") || "").toBe("");
|
|
254
|
+
|
|
255
|
+
// Simulate library updating placeholder due to country change while focused.
|
|
256
|
+
input.setAttribute("placeholder", "+93 123 456 7890");
|
|
257
|
+
act(() => {
|
|
258
|
+
input.dispatchEvent(new Event("countrychange", { bubbles: true }));
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Blur should restore the latest country placeholder.
|
|
262
|
+
act(() => {
|
|
263
|
+
fireEvent.blur(input);
|
|
264
|
+
});
|
|
265
|
+
await waitFor(() => {
|
|
266
|
+
expect(input.getAttribute("placeholder")).toBe("+93 123 456 7890");
|
|
267
|
+
});
|
|
268
|
+
});
|
|
@@ -5,7 +5,82 @@ import StarterKit from "@tiptap/starter-kit"
|
|
|
5
5
|
import Link from '@tiptap/extension-link'
|
|
6
6
|
|
|
7
7
|
import Select from '../../pb_select/_select'
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
const release = `
|
|
10
|
+
<div>
|
|
11
|
+
<div>
|
|
12
|
+
<strong>Story Background</strong>
|
|
13
|
+
</div>
|
|
14
|
+
<div>
|
|
15
|
+
Follow the{" "}
|
|
16
|
+
<a href='https://github.com/powerhome/playbook/wiki/Release-Team-Guide'>
|
|
17
|
+
release process
|
|
18
|
+
</a>{" "}
|
|
19
|
+
to create a new version, create a gem, and package. Create a Ninja testing
|
|
20
|
+
plan, then update Nitro with the new version.
|
|
21
|
+
</div>
|
|
22
|
+
<div>
|
|
23
|
+
<br />
|
|
24
|
+
</div>
|
|
25
|
+
<div>
|
|
26
|
+
<strong>Timeline / Due Date</strong>
|
|
27
|
+
</div>
|
|
28
|
+
<div>
|
|
29
|
+
<em>Release End of business Thursday</em>
|
|
30
|
+
</div>
|
|
31
|
+
<div>
|
|
32
|
+
<em>Testing on Nitro End of business Friday</em>
|
|
33
|
+
</div>
|
|
34
|
+
<div>
|
|
35
|
+
<br />
|
|
36
|
+
</div>
|
|
37
|
+
<div>
|
|
38
|
+
<strong>Definition of done</strong>
|
|
39
|
+
</div>
|
|
40
|
+
<ol>
|
|
41
|
+
<li>Merge all PR’s</li>
|
|
42
|
+
<li>Update the final CHANGELOG</li>
|
|
43
|
+
<li>Version up and generate NPM, and RubyGem</li>
|
|
44
|
+
<li>Create next version branch and milestone</li>
|
|
45
|
+
<li>Update default branch and branch protection rules </li>
|
|
46
|
+
<li>Notify Everyone of new version</li>
|
|
47
|
+
<li>
|
|
48
|
+
Generate testing plan and pages to test for Ninjas (update runway
|
|
49
|
+
ticket)
|
|
50
|
+
</li>
|
|
51
|
+
<li>Update version on Nitro and get on Demo</li>
|
|
52
|
+
<li>Send Ninjas demo and runway ticket for testing</li>
|
|
53
|
+
<li>Ninja Approved + PR Approved</li>
|
|
54
|
+
</ol>
|
|
55
|
+
<div>
|
|
56
|
+
<br />
|
|
57
|
+
</div>
|
|
58
|
+
<div>
|
|
59
|
+
<strong>Stakeholders / Sign-off</strong>
|
|
60
|
+
</div>
|
|
61
|
+
<ul>
|
|
62
|
+
<li>Code Owners</li>
|
|
63
|
+
</ul>
|
|
64
|
+
<div>
|
|
65
|
+
<br />
|
|
66
|
+
<strong>Cadence</strong>
|
|
67
|
+
<br />
|
|
68
|
+
Jason, Jon, Stephen, Jasper, Brendan, Cole
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
`
|
|
72
|
+
|
|
73
|
+
const changelog = `
|
|
74
|
+
<div>
|
|
75
|
+
<strong>Changelog:<br></strong>
|
|
76
|
+
[INSERT LINK]<br><br>
|
|
77
|
+
You can test the normal spots of Playbook rails and react on
|
|
78
|
+
dev docs plus the following:
|
|
79
|
+
</div>
|
|
80
|
+
<div>
|
|
81
|
+
<br>
|
|
82
|
+
</div>
|
|
83
|
+
`
|
|
9
84
|
|
|
10
85
|
const RichTextEditorAdvancedTemplates = (props) => {
|
|
11
86
|
|
|
@@ -17,7 +17,7 @@ const languages = [
|
|
|
17
17
|
{ label: 'PHP', value: '1995', category: 'Web Development' },
|
|
18
18
|
]
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const colorOptions = [
|
|
21
21
|
{ label: 'Orange', value: '#FFA500' },
|
|
22
22
|
{ label: 'Red', value: '#FF0000' },
|
|
23
23
|
{ label: 'Green', value: '#00FF00' },
|
|
@@ -51,7 +51,7 @@ const TypeaheadReactHook = (props) => {
|
|
|
51
51
|
<Typeahead
|
|
52
52
|
label="Colors"
|
|
53
53
|
marginTop="lg"
|
|
54
|
-
options={
|
|
54
|
+
options={colorOptions}
|
|
55
55
|
{...props}
|
|
56
56
|
{...register('color')}
|
|
57
57
|
/>
|