playbook_ui 15.6.0.pre.alpha.play266013023 → 15.6.0.pre.rc.0
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_table_props.html.erb +163 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props.jsx +190 -0
- data/app/pb_kits/playbook/pb_background/_background.tsx +6 -6
- data/app/pb_kits/playbook/pb_background/background.test.js +1 -5
- data/app/pb_kits/playbook/pb_background/docs/_background_light.html.erb +1 -1
- data/app/pb_kits/playbook/pb_background/docs/_background_light.jsx +1 -0
- data/app/pb_kits/playbook/pb_background/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_card/docs/_card_header.md +1 -1
- data/app/pb_kits/playbook/pb_card/docs/_card_highlight.md +1 -1
- data/app/pb_kits/playbook/pb_collapsible/__snapshots__/collapsible.test.js.snap +2 -2
- data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleIcon.tsx +8 -10
- data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_icons.jsx +1 -0
- data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_state.jsx +3 -0
- data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +0 -24
- data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +3 -181
- data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +1 -2
- data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +1 -1
- data/app/pb_kits/playbook/pb_dialog/dialog.rb +0 -1
- data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +0 -14
- data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +4 -5
- data/app/pb_kits/playbook/pb_dialog/dialog_header.rb +0 -2
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_compound_components.html.erb +0 -31
- data/app/pb_kits/playbook/pb_dialog/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_dialog/docs/index.js +1 -2
- data/app/pb_kits/playbook/pb_distribution_bar/docs/_distribution_bar_custom_colors.md +1 -1
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +7 -458
- data/app/pb_kits/playbook/pb_draggable/context/types.ts +3 -8
- data/app/pb_kits/playbook/pb_draggable/docs/example.yml +2 -3
- data/app/pb_kits/playbook/pb_draggable/docs/index.js +1 -2
- data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +1 -77
- data/app/pb_kits/playbook/pb_file_upload/_file_upload.scss +4 -4
- data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +22 -34
- data/app/pb_kits/playbook/pb_home_address_street/city_emphasis.html.erb +12 -16
- data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_default.html.erb +1 -1
- data/app/pb_kits/playbook/pb_home_address_street/none_emphasis.html.erb +12 -16
- data/app/pb_kits/playbook/pb_home_address_street/street_emphasis.html.erb +12 -16
- data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.scss +0 -10
- data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.tsx +15 -66
- data/app/pb_kits/playbook/pb_multiple_users/docs/example.yml +0 -1
- data/app/pb_kits/playbook/pb_multiple_users/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_multiple_users/multiple_users.test.js +0 -25
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +10 -44
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.html.erb +4 -34
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.jsx +7 -16
- data/app/pb_kits/playbook/pb_radio/docs/_radio_error.md +1 -1
- data/app/pb_kits/playbook/pb_select/_select.tsx +3 -8
- data/app/pb_kits/playbook/pb_select/docs/_select_error.md +1 -1
- data/app/pb_kits/playbook/pb_select/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_select/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
- data/app/pb_kits/playbook/pb_select/select.rb +1 -3
- data/app/pb_kits/playbook/pb_select/select.test.js +0 -23
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.md +1 -1
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.md +1 -1
- data/app/pb_kits/playbook/pb_timeline/_item.tsx +0 -3
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_date.md +1 -1
- data/app/pb_kits/playbook/pb_timeline/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_timeline/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_timeline/item.html.erb +1 -1
- data/app/pb_kits/playbook/pb_timeline/item.rb +0 -2
- data/app/pb_kits/playbook/pb_timeline/label.html.erb +1 -2
- data/app/pb_kits/playbook/pb_timeline/label.rb +0 -2
- data/app/pb_kits/playbook/pb_timeline/subcomponents/Label.tsx +0 -3
- data/app/pb_kits/playbook/pb_timeline/timeline.test.js +0 -51
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +0 -15
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +0 -3
- data/app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.tsx +2 -13
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +1 -6
- data/app/pb_kits/playbook/pb_typeahead/components/ValueContainer.tsx +7 -34
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -2
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +1 -6
- data/app/pb_kits/playbook/tokens/_colors.scss +1 -2
- data/dist/chunks/_typeahead-kRdz5zPn.js +6 -0
- data/dist/chunks/lib-CgpqUb6l.js +29 -0
- data/dist/chunks/vendor.js +2 -2
- 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/forms/builder/collection_select_field.rb +1 -9
- data/lib/playbook/forms/builder/select_field.rb +1 -9
- data/lib/playbook/forms/builder/time_zone_select_field.rb +1 -9
- data/lib/playbook/pb_kit_helper.rb +0 -35
- data/lib/playbook/version.rb +2 -2
- metadata +4 -22
- data/app/pb_kits/playbook/pb_background/docs/_background_light.md +0 -1
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_closeable.html.erb +0 -24
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_closeable.jsx +0 -60
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_closeable.md +0 -3
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_dropzone.jsx +0 -180
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_dropzone.md +0 -22
- data/app/pb_kits/playbook/pb_multiple_users/docs/_multiple_users_with_tooltip.jsx +0 -42
- data/app/pb_kits/playbook/pb_multiple_users/docs/_multiple_users_with_tooltip.md +0 -1
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.html.erb +0 -16
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.jsx +0 -30
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.md +0 -1
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.html.erb +0 -60
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.jsx +0 -118
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.md +0 -1
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_input_display.html.erb +0 -30
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_input_display.jsx +0 -37
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_input_display.md +0 -3
- data/app/pb_kits/playbook/utilities/deprecated.ts +0 -73
- data/dist/chunks/_typeahead-CYNrKU10.js +0 -6
- data/dist/chunks/lib-DDDLiZuu.js +0 -29
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
.pb_file_upload_kit {
|
|
2
|
-
.
|
|
2
|
+
.pb_card_kit_deselected_border_radius_md {
|
|
3
3
|
border: 1px #ccc dashed;
|
|
4
4
|
text-align: center;
|
|
5
5
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
}
|
|
12
12
|
&.error,
|
|
13
13
|
&.pb_file_upload_kit_error {
|
|
14
|
-
.
|
|
14
|
+
.pb_card_kit_deselected_border_radius_md {
|
|
15
15
|
border-color: $error;
|
|
16
16
|
}
|
|
17
17
|
.pb_body_kit_negative {
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
.dark .pb_file_upload_kit {
|
|
33
|
-
.
|
|
33
|
+
.pb_card_kit_deselected_border_radius_md {
|
|
34
34
|
border: 1px $text_dk_lighter dashed;
|
|
35
35
|
}
|
|
36
36
|
&.error,
|
|
37
37
|
&.pb_file_upload_kit_error {
|
|
38
|
-
.
|
|
38
|
+
.pb_card_kit_deselected_border_radius_md {
|
|
39
39
|
border-color: $error_dark;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -96,24 +96,20 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
|
96
96
|
{hasAllEmptyProps && '—'}
|
|
97
97
|
{emphasis == 'street' && !hasAllEmptyProps &&
|
|
98
98
|
<div>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
>
|
|
114
|
-
{titleize(addressCont)}
|
|
115
|
-
</Title>
|
|
116
|
-
)}
|
|
99
|
+
<Title
|
|
100
|
+
className="pb_home_address_street_address"
|
|
101
|
+
dark={dark}
|
|
102
|
+
size={4}
|
|
103
|
+
>
|
|
104
|
+
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
|
105
|
+
</Title>
|
|
106
|
+
<Title
|
|
107
|
+
className="pb_home_address_street_address"
|
|
108
|
+
dark={dark}
|
|
109
|
+
size={4}
|
|
110
|
+
>
|
|
111
|
+
{titleize(addressCont)}
|
|
112
|
+
</Title>
|
|
117
113
|
<Body color="light">
|
|
118
114
|
{`${city ? `${titleize(city)}, ` : ''}${uppercaseState}${zipcode ? ` ${zipcode}` : ''}`}
|
|
119
115
|
</Body>
|
|
@@ -121,14 +117,10 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
|
121
117
|
}
|
|
122
118
|
{emphasis == 'city' && !hasAllEmptyProps &&
|
|
123
119
|
<div>
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
)}
|
|
129
|
-
{addressCont && (
|
|
130
|
-
<Body color="light">{titleize(addressCont)}</Body>
|
|
131
|
-
)}
|
|
120
|
+
<Body color="light">
|
|
121
|
+
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
|
122
|
+
</Body>
|
|
123
|
+
<Body color="light">{titleize(addressCont)}</Body>
|
|
132
124
|
<div>
|
|
133
125
|
<Title
|
|
134
126
|
className="pb_home_address_street_address"
|
|
@@ -149,14 +141,10 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
|
149
141
|
}
|
|
150
142
|
{emphasis == 'none' && !hasAllEmptyProps &&
|
|
151
143
|
<div>
|
|
152
|
-
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
)}
|
|
157
|
-
{addressCont && (
|
|
158
|
-
<Body dark={dark}>{formatStreetAdr(addressCont)}</Body>
|
|
159
|
-
)}
|
|
144
|
+
<Body dark={dark}>
|
|
145
|
+
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
|
146
|
+
</Body>
|
|
147
|
+
<Body dark={dark}>{formatStreetAdr(addressCont)}</Body>
|
|
160
148
|
<div>
|
|
161
149
|
<Body
|
|
162
150
|
color="light"
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
text: object.address_house_style2,
|
|
14
|
-
dark: object.dark
|
|
15
|
-
} %>
|
|
16
|
-
<% end %>
|
|
1
|
+
<%= pb_rails "body", props: {
|
|
2
|
+
classname: "pb_home_address_street_address",
|
|
3
|
+
color: "light",
|
|
4
|
+
text: object.address_house_style,
|
|
5
|
+
dark: object.dark
|
|
6
|
+
} %>
|
|
7
|
+
<%= pb_rails "body", props: {
|
|
8
|
+
classname: "pb_home_address_street_address",
|
|
9
|
+
color: "light",
|
|
10
|
+
text: object.address_house_style2,
|
|
11
|
+
dark: object.dark
|
|
12
|
+
} %>
|
|
17
13
|
<div>
|
|
18
14
|
<%= pb_rails "title", props: {
|
|
19
15
|
tag: "span",
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
text: object.address_house_style2,
|
|
14
|
-
dark: object.dark
|
|
15
|
-
} %>
|
|
16
|
-
<% end %>
|
|
1
|
+
<%= pb_rails "body", props: {
|
|
2
|
+
classname: "pb_home_address_street_address",
|
|
3
|
+
size: 4,
|
|
4
|
+
text: object.address_house_style,
|
|
5
|
+
dark: object.dark
|
|
6
|
+
} %>
|
|
7
|
+
<%= pb_rails "body", props: {
|
|
8
|
+
classname: "pb_home_address_street_address",
|
|
9
|
+
size: 4,
|
|
10
|
+
text: object.address_house_style2,
|
|
11
|
+
dark: object.dark
|
|
12
|
+
} %>
|
|
17
13
|
<%= pb_rails "body", props: {
|
|
18
14
|
color: "light",
|
|
19
15
|
text: object.city_state_zip,
|
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
text: object.address_house_style2,
|
|
14
|
-
dark: object.dark
|
|
15
|
-
} %>
|
|
16
|
-
<% end %>
|
|
1
|
+
<%= pb_rails "title", props: {
|
|
2
|
+
classname: "pb_home_address_street_address",
|
|
3
|
+
size: 4,
|
|
4
|
+
text: object.address_house_style,
|
|
5
|
+
dark: object.dark
|
|
6
|
+
} %>
|
|
7
|
+
<%= pb_rails "title", props: {
|
|
8
|
+
classname: "pb_home_address_street_address",
|
|
9
|
+
size: 4,
|
|
10
|
+
text: object.address_house_style2,
|
|
11
|
+
dark: object.dark
|
|
12
|
+
} %>
|
|
17
13
|
<%= pb_rails "body", props: {
|
|
18
14
|
color: "light",
|
|
19
15
|
text: object.city_state_zip,
|
|
@@ -36,16 +36,6 @@ $pb_multiple_users_size_xxs: map-get($avatar-sizes, "xxs");
|
|
|
36
36
|
height: $pb_multiple_users_size_xxs;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
.user_tooltip {
|
|
41
|
-
margin-left: $pb_multiple_users_overlap !important;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.user_count_tooltip {
|
|
45
|
-
margin-left: $pb_multiple_users_overlap !important;
|
|
46
|
-
position: relative;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
39
|
.pb_multiple_users_item {
|
|
50
40
|
margin-left: $pb_multiple_users_overlap;
|
|
51
41
|
margin-right: 0;
|
|
@@ -5,19 +5,17 @@ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../uti
|
|
|
5
5
|
import { globalProps } from '../utilities/globalProps'
|
|
6
6
|
|
|
7
7
|
import Avatar from '../pb_avatar/_avatar'
|
|
8
|
-
import Tooltip from '../pb_tooltip/_tooltip'
|
|
9
8
|
|
|
10
9
|
type MultipleUsersProps = {
|
|
11
10
|
aria?: { [key: string]: string },
|
|
12
11
|
className?: string,
|
|
13
12
|
dark?: boolean,
|
|
14
13
|
data?: { [key: string]: string },
|
|
15
|
-
htmlOptions?: {
|
|
14
|
+
htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
|
|
16
15
|
id?: string,
|
|
17
16
|
maxDisplayedUsers?: number,
|
|
18
17
|
reverse?: boolean,
|
|
19
18
|
size?: "md" | "lg" | "sm" | "xl" | "xs" | "xxs",
|
|
20
|
-
withTooltip?: boolean,
|
|
21
19
|
users: Array<{ [key: string]: string }>,
|
|
22
20
|
}
|
|
23
21
|
|
|
@@ -32,7 +30,6 @@ const MultipleUsers = (props: MultipleUsersProps): React.ReactElement => {
|
|
|
32
30
|
maxDisplayedUsers = 4,
|
|
33
31
|
reverse = false,
|
|
34
32
|
size = 'xs',
|
|
35
|
-
withTooltip = false,
|
|
36
33
|
users,
|
|
37
34
|
} = props
|
|
38
35
|
|
|
@@ -65,70 +62,22 @@ const MultipleUsers = (props: MultipleUsersProps): React.ReactElement => {
|
|
|
65
62
|
className={classes}
|
|
66
63
|
id={id}
|
|
67
64
|
>
|
|
68
|
-
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{...avatarData}
|
|
79
|
-
className={"pb_multiple_users_item" + (withTooltip ? " user_tooltip" : "")}
|
|
80
|
-
dark={dark}
|
|
81
|
-
imageAlt={avatarData.name}
|
|
82
|
-
key={index}
|
|
83
|
-
size={size}
|
|
84
|
-
/>
|
|
85
|
-
</Tooltip>
|
|
86
|
-
))}
|
|
65
|
+
{usersToDisplay.map((avatarData, index) => (
|
|
66
|
+
<Avatar
|
|
67
|
+
{...avatarData}
|
|
68
|
+
className="pb_multiple_users_item"
|
|
69
|
+
dark={dark}
|
|
70
|
+
imageAlt={avatarData.name}
|
|
71
|
+
key={index}
|
|
72
|
+
size={size}
|
|
73
|
+
/>
|
|
74
|
+
))}
|
|
87
75
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<div>
|
|
93
|
-
{
|
|
94
|
-
usersToDisplay.length < users.length ?
|
|
95
|
-
users.slice(displayCount).map((u, i) => (
|
|
96
|
-
<div key={i}>{u.tooltip}</div>
|
|
97
|
-
))
|
|
98
|
-
:
|
|
99
|
-
''
|
|
100
|
-
}
|
|
101
|
-
</div>
|
|
102
|
-
}
|
|
103
|
-
zIndex={10}
|
|
104
|
-
>
|
|
105
|
-
<div className={itemClasses + (withTooltip ? " user_count_tooltip" : "")}>
|
|
106
|
-
{`+${users.length - displayCount}`}
|
|
107
|
-
</div>
|
|
108
|
-
</Tooltip>
|
|
109
|
-
}
|
|
110
|
-
</>
|
|
111
|
-
:
|
|
112
|
-
<>
|
|
113
|
-
{usersToDisplay.map((avatarData, index) => (
|
|
114
|
-
<Avatar
|
|
115
|
-
{...avatarData}
|
|
116
|
-
className="pb_multiple_users_item"
|
|
117
|
-
dark={dark}
|
|
118
|
-
imageAlt={avatarData.name}
|
|
119
|
-
key={index}
|
|
120
|
-
size={size}
|
|
121
|
-
/>
|
|
122
|
-
))}
|
|
123
|
-
|
|
124
|
-
{users.length > maxDisplayedUsers &&
|
|
125
|
-
<div className={itemClasses}>
|
|
126
|
-
{`+${users.length - 3}`}
|
|
127
|
-
</div>
|
|
128
|
-
}
|
|
129
|
-
</>
|
|
76
|
+
{ users.length > maxDisplayedUsers &&
|
|
77
|
+
<div className={itemClasses}>
|
|
78
|
+
{`+${users.length - 3}`}
|
|
79
|
+
</div>
|
|
130
80
|
}
|
|
131
|
-
|
|
132
81
|
</div>
|
|
133
82
|
)
|
|
134
83
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
export { default as MultipleUsersDefault } from './_multiple_users_default.jsx'
|
|
2
2
|
export { default as MultipleUsersReverse } from './_multiple_users_reverse.jsx'
|
|
3
3
|
export { default as MultipleUsersSize } from './_multiple_users_size.jsx'
|
|
4
|
-
export { default as MultipleUsersWithTooltip } from './_multiple_users_with_tooltip.jsx'
|
|
@@ -49,29 +49,4 @@ test('should render aria-label', () => {
|
|
|
49
49
|
|
|
50
50
|
const kit = screen.getByTestId(testId)
|
|
51
51
|
expect(kit).toHaveAttribute('aria-label', testId)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('should render withTooltip prop', () => {
|
|
55
|
-
render(
|
|
56
|
-
<MultipleUsers
|
|
57
|
-
data={{ testid: testId }}
|
|
58
|
-
users={[
|
|
59
|
-
{
|
|
60
|
-
name: 'Patrick Welch',
|
|
61
|
-
imageUrl: 'https://randomuser.me/api/portraits/men/9.jpg',
|
|
62
|
-
tooltip: "Patrick Welch - Online"
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'Lucille Sanchez',
|
|
66
|
-
imageUrl: 'https://randomuser.me/api/portraits/women/6.jpg',
|
|
67
|
-
tooltip: "Lucille Sanchez - Offline"
|
|
68
|
-
},
|
|
69
|
-
]}
|
|
70
|
-
withTooltip
|
|
71
|
-
/>
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
const kit = screen.getByTestId(testId)
|
|
75
|
-
const childWithTooltip = kit.querySelector('.pb_tooltip_kit')
|
|
76
|
-
expect(childWithTooltip).not.toBeNull()
|
|
77
52
|
})
|
|
@@ -110,25 +110,13 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
110
110
|
const inputRef = useRef<HTMLInputElement | null>(null)
|
|
111
111
|
const itiRef = useRef<any>(null);
|
|
112
112
|
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
|
113
|
-
const hasBlurredRef = useRef<boolean>(false);
|
|
114
|
-
const formSubmittedRef = useRef<boolean>(false);
|
|
115
113
|
const [inputValue, setInputValue] = useState(value)
|
|
116
114
|
const [error, setError] = useState(props.error || "")
|
|
117
115
|
const [dropDownIsOpen, setDropDownIsOpen] = useState(false)
|
|
118
116
|
const [selectedData, setSelectedData] = useState()
|
|
119
117
|
const [hasTyped, setHasTyped] = useState(false)
|
|
120
|
-
const [hasBlurred, setHasBlurred] = useState(false)
|
|
121
118
|
const [formSubmitted, setFormSubmitted] = useState(false)
|
|
122
119
|
const [hasStartedValidating, setHasStartedValidating] = useState(false)
|
|
123
|
-
|
|
124
|
-
// Keep refs in sync with state for use in event listeners
|
|
125
|
-
useEffect(() => {
|
|
126
|
-
hasBlurredRef.current = hasBlurred
|
|
127
|
-
}, [hasBlurred])
|
|
128
|
-
|
|
129
|
-
useEffect(() => {
|
|
130
|
-
formSubmittedRef.current = formSubmitted
|
|
131
|
-
}, [formSubmitted])
|
|
132
120
|
|
|
133
121
|
// Only sync initial error from props, not continuous updates
|
|
134
122
|
// Once validation starts, internal validation takes over
|
|
@@ -155,8 +143,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
155
143
|
}
|
|
156
144
|
|
|
157
145
|
// Determine which error to display
|
|
158
|
-
// Show internal errors
|
|
159
|
-
const shouldShowInternalError = (
|
|
146
|
+
// Show internal errors on blur (hasTyped) or on form submission (formSubmitted)
|
|
147
|
+
const shouldShowInternalError = (hasTyped || formSubmitted) && required && error
|
|
160
148
|
const displayError = shouldShowInternalError ? error : ""
|
|
161
149
|
|
|
162
150
|
useEffect(() => {
|
|
@@ -271,9 +259,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
271
259
|
return
|
|
272
260
|
}
|
|
273
261
|
|
|
274
|
-
|
|
275
|
-
// Use refs here since state updates are async and we need current values
|
|
276
|
-
if (!hasBlurredRef.current && !formSubmittedRef.current) return
|
|
262
|
+
if (!hasTyped && !error) return
|
|
277
263
|
|
|
278
264
|
// Run validation checks
|
|
279
265
|
if (itiRef.current) isValid(itiRef.current.isValidNumber())
|
|
@@ -294,7 +280,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
294
280
|
if (phoneNumberContainer && phoneNumberContainer === wrapperRef.current) {
|
|
295
281
|
const invalidInputName = target.name || target.getAttribute('name')
|
|
296
282
|
if (invalidInputName === name) {
|
|
297
|
-
formSubmittedRef.current = true
|
|
298
283
|
setFormSubmitted(true)
|
|
299
284
|
// Trigger validation when form is submitted
|
|
300
285
|
validateErrors()
|
|
@@ -320,9 +305,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
320
305
|
setInputValue("")
|
|
321
306
|
setError("")
|
|
322
307
|
setHasTyped(false)
|
|
323
|
-
hasBlurredRef.current = false
|
|
324
|
-
setHasBlurred(false)
|
|
325
|
-
formSubmittedRef.current = false
|
|
326
308
|
setFormSubmitted(false)
|
|
327
309
|
setHasStartedValidating(false)
|
|
328
310
|
// Only clear validation state if field was required
|
|
@@ -340,7 +322,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
340
322
|
|
|
341
323
|
if (required && isEmpty) {
|
|
342
324
|
setError('Missing phone number')
|
|
343
|
-
formSubmittedRef.current = true
|
|
344
325
|
setFormSubmitted(true)
|
|
345
326
|
return 'Missing phone number'
|
|
346
327
|
}
|
|
@@ -397,7 +378,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
397
378
|
|
|
398
379
|
// Set the error state so the validation attribute gets added
|
|
399
380
|
setError(errorMessage)
|
|
400
|
-
formSubmittedRef.current = true
|
|
401
381
|
setFormSubmitted(true)
|
|
402
382
|
setHasTyped(true)
|
|
403
383
|
|
|
@@ -421,7 +401,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
421
401
|
|
|
422
402
|
// Reset form submitted state when user types
|
|
423
403
|
if (formSubmitted) {
|
|
424
|
-
formSubmittedRef.current = false
|
|
425
404
|
setFormSubmitted(false)
|
|
426
405
|
}
|
|
427
406
|
|
|
@@ -437,15 +416,11 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
437
416
|
|
|
438
417
|
setSelectedData(phoneNumberData)
|
|
439
418
|
onChange(phoneNumberData)
|
|
440
|
-
|
|
441
|
-
// Don't call isValid callback on change - only on blur or form submission
|
|
442
|
-
// This prevents triggering validation while typing
|
|
443
|
-
// Use refs to get current values in case this is called from event listener
|
|
444
|
-
if (hasBlurredRef.current || formSubmittedRef.current) {
|
|
445
|
-
isValid(itiRef.current.isValidNumber())
|
|
446
|
-
}
|
|
419
|
+
isValid(itiRef.current.isValidNumber())
|
|
447
420
|
|
|
448
|
-
//
|
|
421
|
+
// Trigger validation after onChange for React Hook Form
|
|
422
|
+
// This ensures validation state is up-to-date
|
|
423
|
+
setTimeout(() => validateErrors(), 0)
|
|
449
424
|
}
|
|
450
425
|
|
|
451
426
|
// Separating Concerns as React Docs Recommend
|
|
@@ -507,12 +482,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
507
482
|
|
|
508
483
|
setSelectedData(phoneNumberData)
|
|
509
484
|
onChange(phoneNumberData)
|
|
510
|
-
|
|
511
|
-
// Don't call isValid callback on change - only on blur or form submission
|
|
512
|
-
// Use refs to check current blur state in the event listener (closure issue)
|
|
513
|
-
if (hasBlurredRef.current || formSubmittedRef.current) {
|
|
514
|
-
isValid(telInputInit.isValidNumber())
|
|
515
|
-
}
|
|
485
|
+
isValid(telInputInit.isValidNumber())
|
|
516
486
|
})
|
|
517
487
|
}
|
|
518
488
|
}
|
|
@@ -522,16 +492,12 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.Ref<unknown>
|
|
|
522
492
|
dark,
|
|
523
493
|
"data-phone-number": JSON.stringify(selectedData),
|
|
524
494
|
disabled,
|
|
525
|
-
error:
|
|
495
|
+
error: hasTyped ? error : props.error || displayError,
|
|
526
496
|
type: 'tel',
|
|
527
497
|
id,
|
|
528
498
|
label,
|
|
529
499
|
name,
|
|
530
|
-
onBlur:
|
|
531
|
-
hasBlurredRef.current = true
|
|
532
|
-
setHasBlurred(true)
|
|
533
|
-
validateErrors()
|
|
534
|
-
},
|
|
500
|
+
onBlur: validateErrors,
|
|
535
501
|
onChange: formatAsYouType ? undefined : handleOnChange,
|
|
536
502
|
value: inputValue
|
|
537
503
|
}
|
data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.html.erb
CHANGED
|
@@ -1,42 +1,12 @@
|
|
|
1
1
|
<form id="example-form-validation" action="" method="get">
|
|
2
|
-
<%= pb_rails("phone_number_input", props: {
|
|
3
|
-
id: "validation",
|
|
4
|
-
initial_country: "af",
|
|
5
|
-
value: "",
|
|
6
|
-
required: true
|
|
7
|
-
}) %>
|
|
2
|
+
<%= pb_rails("phone_number_input", props: { error: "Missing phone number", id: "validation", initial_country: "af", value: "", required: true }) %>
|
|
8
3
|
<%= pb_rails("button", props: {html_type: "submit", text: "Save Phone Number"}) %>
|
|
9
4
|
</form>
|
|
10
5
|
|
|
11
6
|
<%= javascript_tag do %>
|
|
12
7
|
document.addEventListener('DOMContentLoaded', function () {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
function waitForComponent() {
|
|
17
|
-
const phoneInput = form.querySelector('#validation');
|
|
18
|
-
|
|
19
|
-
if (!phoneInput) {
|
|
20
|
-
setTimeout(waitForComponent, 100);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Wait for intl-tel-input to initialize, then focus and blur to trigger validation
|
|
25
|
-
setTimeout(function() {
|
|
26
|
-
phoneInput.focus({ preventScroll: true });
|
|
27
|
-
setTimeout(function() {
|
|
28
|
-
phoneInput.blur();
|
|
29
|
-
}, 100);
|
|
30
|
-
}, 500);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
waitForComponent();
|
|
34
|
-
|
|
35
|
-
// Prevent form submission if there are validation errors
|
|
36
|
-
form.addEventListener('submit', function (e) {
|
|
37
|
-
if (e.target.querySelectorAll('[error]:not([error=""])').length > 0) {
|
|
38
|
-
e.preventDefault();
|
|
39
|
-
}
|
|
40
|
-
});
|
|
8
|
+
document.querySelector('#example-form-validation').addEventListener('submit', function (e) {
|
|
9
|
+
if (e.target.querySelectorAll('[error]:not([error=""])').length > 0) e.preventDefault();
|
|
10
|
+
})
|
|
41
11
|
})
|
|
42
12
|
<% end %>
|
|
@@ -10,19 +10,8 @@ const PhoneNumberInputValidation = (props) => {
|
|
|
10
10
|
const [showFormErrors, setShowFormErrors] = useState(false);
|
|
11
11
|
const [phoneNumber, setPhoneNumber] = useState("");
|
|
12
12
|
const [countryCode, setCountryCode] = useState("af");
|
|
13
|
-
const [isValid, setIsValid] = useState(false);
|
|
14
|
-
const [hasInteracted, setHasInteracted] = useState(false);
|
|
15
|
-
|
|
16
|
-
// Start with initial error - will be cleared on blur if valid
|
|
17
|
-
const initialError = (
|
|
18
|
-
<>
|
|
19
|
-
<Icon icon="warning" /> Missing phone number.
|
|
20
|
-
</>
|
|
21
|
-
);
|
|
22
13
|
|
|
23
14
|
const handleOnValidate = (valid) => {
|
|
24
|
-
setIsValid(valid);
|
|
25
|
-
setHasInteracted(true);
|
|
26
15
|
setFormErrors(
|
|
27
16
|
valid ? "" : "Please correct the fields below and try again."
|
|
28
17
|
);
|
|
@@ -34,16 +23,18 @@ const PhoneNumberInputValidation = (props) => {
|
|
|
34
23
|
};
|
|
35
24
|
|
|
36
25
|
const handleOnSubmit = (e) => {
|
|
37
|
-
if (
|
|
26
|
+
if (showFormErrors) e.preventDefault()
|
|
38
27
|
}
|
|
39
28
|
|
|
40
29
|
useEffect(() => {
|
|
41
30
|
setShowFormErrors(formErrors.length > 0);
|
|
42
31
|
}, [formErrors]);
|
|
43
32
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
33
|
+
const error = (
|
|
34
|
+
<>
|
|
35
|
+
<Icon icon="warning" /> Missing phone number.
|
|
36
|
+
</>
|
|
37
|
+
)
|
|
47
38
|
|
|
48
39
|
return (
|
|
49
40
|
<form
|
|
@@ -59,7 +50,7 @@ const PhoneNumberInputValidation = (props) => {
|
|
|
59
50
|
/>
|
|
60
51
|
)}
|
|
61
52
|
<PhoneNumberInput
|
|
62
|
-
error={
|
|
53
|
+
error={error}
|
|
63
54
|
id="validation"
|
|
64
55
|
initialCountry={countryCode}
|
|
65
56
|
onChange={handleOnChange}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Error shows that the radio option must be selected or is invalid (
|
|
1
|
+
Error shows that the radio option must be selected or is invalid (ie when used in a form it signals a user to fix an error).
|