playbook_ui 15.1.0.pre.alpha.play252710946 → 15.1.0.pre.alpha.testingtiptap11004
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/Hooks/useTableState.ts +0 -2
- data/app/pb_kits/playbook/pb_date_picker/_date_picker.scss +4 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.html.erb +16 -16
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_stacked_alert.jsx +2 -1
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.html.erb +31 -31
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_status.jsx +4 -3
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -12
- data/app/pb_kits/playbook/pb_rich_text_editor/_previewer_mixin.scss +3 -13
- data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +0 -10
- data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +14 -6
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.html.erb +8 -4
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.jsx +5 -0
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_default.md +1 -0
- data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +3 -1
- data/app/pb_kits/playbook/pb_text_input/text_input.rb +6 -0
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +1 -39
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +0 -2
- data/dist/chunks/{_line_graph-DwC5jqYQ.js → _line_graph-BnK1i7QI.js} +1 -1
- data/dist/chunks/{_typeahead-4Ud3FHDA.js → _typeahead-pbS3fEzb.js} +1 -1
- data/dist/chunks/{_weekday_stacked-CygSRiZe.js → _weekday_stacked-OOFiMFSs.js} +2 -2
- data/dist/chunks/vendor.js +1 -1
- data/dist/playbook-doc.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/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7666b6fac1ed12cd57f6e04399e9435d460a274c5d44d38216ce0ed94024cde7
|
4
|
+
data.tar.gz: de5912fdd691035fb02f2a92d9692309a08586ec430141ee8ed0b64ee5b3e70e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60685d79142f02e761606168b87b47bd68384f8f112270e2a77ffd8233b02660fd949ddc288160a769dad5ce70e32a814509f90dd15b6b4cd6bcfb51088cde41
|
7
|
+
data.tar.gz: 3b8ceb9c5588c986fd04fcbbdf230e5d6a0a2852afd72d11d4c06685433b717e468e44ee9ec63756fbbe887812f9977a7013f87e62ca1e07108acc22aeb2eb41
|
@@ -3,12 +3,12 @@
|
|
3
3
|
<%= pb_rails("button", props: { text: "Delete Status", data: {"open-dialog": "dialog-stacked-delete"}, margin_right: "md" }) %>
|
4
4
|
|
5
5
|
|
6
|
-
<%= pb_rails("dialog", props: {
|
7
|
-
id:"dialog-stacked-default",
|
6
|
+
<%= pb_rails("dialog", props: {
|
7
|
+
id:"dialog-stacked-default",
|
8
8
|
status: "default",
|
9
|
-
size: "sm",
|
10
|
-
title: "Are you sure?",
|
11
|
-
text: "Text explaining why there is an alert",
|
9
|
+
size: "sm",
|
10
|
+
title: "Are you sure?",
|
11
|
+
text: "Text explaining why there is an alert",
|
12
12
|
}) do %>
|
13
13
|
<%= pb_rails("dialog/dialog_footer") do %>
|
14
14
|
<%= pb_rails("flex", props: { orientation: "column", padding_x:"md", padding: "sm" }) do %>
|
@@ -18,12 +18,12 @@
|
|
18
18
|
<% end %>
|
19
19
|
<% end %>
|
20
20
|
|
21
|
-
<%= pb_rails("dialog", props: {
|
22
|
-
id:"dialog-stacked-caution",
|
21
|
+
<%= pb_rails("dialog", props: {
|
22
|
+
id:"dialog-stacked-caution",
|
23
23
|
status: "caution",
|
24
|
-
size: "sm",
|
25
|
-
title: "Are you sure?",
|
26
|
-
text: "This is the action you will be taking",
|
24
|
+
size: "sm",
|
25
|
+
title: "Are you sure?",
|
26
|
+
text: "This is the action you will be taking",
|
27
27
|
}) do %>
|
28
28
|
<%= pb_rails("dialog/dialog_footer") do %>
|
29
29
|
<%= pb_rails("flex", props: { orientation: "column", padding_x:"md", padding: "sm" }) do %>
|
@@ -33,16 +33,16 @@
|
|
33
33
|
<% end %>
|
34
34
|
<% end %>
|
35
35
|
|
36
|
-
<%= pb_rails("dialog", props: {
|
37
|
-
id:"dialog-stacked-delete",
|
36
|
+
<%= pb_rails("dialog", props: {
|
37
|
+
id:"dialog-stacked-delete",
|
38
38
|
status: "delete",
|
39
|
-
size: "sm",
|
40
|
-
title: "Delete",
|
41
|
-
text: "You are about to delete ...",
|
39
|
+
size: "sm",
|
40
|
+
title: "Delete",
|
41
|
+
text: "You are about to delete ...",
|
42
42
|
}) do %>
|
43
43
|
<%= pb_rails("dialog/dialog_footer") do %>
|
44
44
|
<%= pb_rails("flex", props: { orientation: "column", padding_x:"md", padding: "sm" }) do %>
|
45
|
-
<%= pb_rails("button", props: { text: "Yes, Action", full_width: true }) %>
|
45
|
+
<%= pb_rails("button", props: { text: "Yes, Action", variant: "danger", full_width: true }) %>
|
46
46
|
<%= pb_rails("button", props: { text: "No, Cancel", variant: "secondary", full_width: true, margin_top: "sm", data: {"close-dialog": "dialog-stacked-delete" } }) %>
|
47
47
|
<% end %>
|
48
48
|
<% end %>
|
@@ -51,7 +51,7 @@ const DialogStackedAlert = () => {
|
|
51
51
|
return (
|
52
52
|
<div>
|
53
53
|
<Flex
|
54
|
-
rowGap="xs"
|
54
|
+
rowGap="xs"
|
55
55
|
wrap
|
56
56
|
>
|
57
57
|
<Button
|
@@ -93,6 +93,7 @@ const DialogStackedAlert = () => {
|
|
93
93
|
<Button
|
94
94
|
fullWidth
|
95
95
|
onClick={dialog.toggle}
|
96
|
+
variant= {dialog.status == "delete" ? "danger" : "primary"}
|
96
97
|
>
|
97
98
|
{dialog.buttonOneText}
|
98
99
|
</Button>
|
@@ -8,12 +8,12 @@
|
|
8
8
|
<%= pb_rails("button", props: { text: "Success Status", data: {"open-dialog": "dialog-status-success"}, margin_right: "md" }) %>
|
9
9
|
<% end %>
|
10
10
|
|
11
|
-
<%= pb_rails("dialog", props: {
|
12
|
-
id:"dialog-status-default",
|
11
|
+
<%= pb_rails("dialog", props: {
|
12
|
+
id:"dialog-status-default",
|
13
13
|
status: "default",
|
14
|
-
size: "status_size",
|
15
|
-
title: "Are you sure?",
|
16
|
-
text: "Text explaining why there is an alert",
|
14
|
+
size: "status_size",
|
15
|
+
title: "Are you sure?",
|
16
|
+
text: "Text explaining why there is an alert",
|
17
17
|
}) do %>
|
18
18
|
<%= pb_rails("dialog/dialog_footer") do %>
|
19
19
|
<%= pb_rails("flex", props: { spacing:"between", padding_x:"md", padding_bottom:"md", padding: "sm" }) do %>
|
@@ -23,12 +23,12 @@
|
|
23
23
|
<% end %>
|
24
24
|
<% end %>
|
25
25
|
|
26
|
-
<%= pb_rails("dialog", props: {
|
27
|
-
id:"dialog-status-info",
|
26
|
+
<%= pb_rails("dialog", props: {
|
27
|
+
id:"dialog-status-info",
|
28
28
|
status: "info",
|
29
|
-
size: "status_size",
|
30
|
-
title: "Information",
|
31
|
-
text: "Text explaining why there is an alert",
|
29
|
+
size: "status_size",
|
30
|
+
title: "Information",
|
31
|
+
text: "Text explaining why there is an alert",
|
32
32
|
}) do %>
|
33
33
|
<%= pb_rails("dialog/dialog_footer") do %>
|
34
34
|
<%= pb_rails("flex", props: { spacing:"between", padding_x:"md", padding_bottom:"md", padding: "sm" }) do %>
|
@@ -37,12 +37,12 @@
|
|
37
37
|
<% end %>
|
38
38
|
<% end %>
|
39
39
|
|
40
|
-
<%= pb_rails("dialog", props: {
|
41
|
-
id:"dialog-status-caution",
|
40
|
+
<%= pb_rails("dialog", props: {
|
41
|
+
id:"dialog-status-caution",
|
42
42
|
status: "caution",
|
43
|
-
size: "status_size",
|
44
|
-
title: "Are you Sure?",
|
45
|
-
text: "This is the action you will be taking",
|
43
|
+
size: "status_size",
|
44
|
+
title: "Are you Sure?",
|
45
|
+
text: "This is the action you will be taking",
|
46
46
|
}) do %>
|
47
47
|
<%= pb_rails("dialog/dialog_footer") do %>
|
48
48
|
<%= pb_rails("flex", props: { spacing:"between", padding_x:"md", padding_bottom:"md", padding: "sm" }) do %>
|
@@ -52,27 +52,27 @@
|
|
52
52
|
<% end %>
|
53
53
|
<% end %>
|
54
54
|
|
55
|
-
<%= pb_rails("dialog", props: {
|
56
|
-
id:"dialog-status-delete",
|
55
|
+
<%= pb_rails("dialog", props: {
|
56
|
+
id:"dialog-status-delete",
|
57
57
|
status: "delete",
|
58
|
-
size: "status_size",
|
59
|
-
title: "Delete",
|
60
|
-
text: "You are about to delete ...",
|
58
|
+
size: "status_size",
|
59
|
+
title: "Delete",
|
60
|
+
text: "You are about to delete ...",
|
61
61
|
}) do %>
|
62
62
|
<%= pb_rails("dialog/dialog_footer") do %>
|
63
63
|
<%= pb_rails("flex", props: { spacing:"between", padding_x:"md", padding_bottom:"md", padding: "sm" }) do %>
|
64
|
-
<%= pb_rails("button", props: { text: "Yes, Delete" }) %>
|
64
|
+
<%= pb_rails("button", props: { text: "Yes, Delete", variant: "danger" }) %>
|
65
65
|
<%= pb_rails("button", props: { text: "No, Cancel", variant: "secondary", data: {"close-dialog": "dialog-status-delete" } }) %>
|
66
66
|
<% end %>
|
67
67
|
<% end %>
|
68
68
|
<% end %>
|
69
69
|
|
70
|
-
<%= pb_rails("dialog", props: {
|
71
|
-
id:"dialog-status-error",
|
70
|
+
<%= pb_rails("dialog", props: {
|
71
|
+
id:"dialog-status-error",
|
72
72
|
status: "error",
|
73
|
-
size: "status_size",
|
74
|
-
title: "Error Message",
|
75
|
-
text: "Text explaining the error",
|
73
|
+
size: "status_size",
|
74
|
+
title: "Error Message",
|
75
|
+
text: "Text explaining the error",
|
76
76
|
}) do %>
|
77
77
|
<%= pb_rails("dialog/dialog_footer") do %>
|
78
78
|
<%= pb_rails("flex", props: { spacing:"between", padding_x:"md", padding_bottom:"md", padding: "sm" }) do %>
|
@@ -81,12 +81,12 @@
|
|
81
81
|
<% end %>
|
82
82
|
<% end %>
|
83
83
|
|
84
|
-
<%= pb_rails("dialog", props: {
|
85
|
-
id:"dialog-status-success",
|
84
|
+
<%= pb_rails("dialog", props: {
|
85
|
+
id:"dialog-status-success",
|
86
86
|
status: "success",
|
87
|
-
size: "status_size",
|
88
|
-
title: "Success!",
|
89
|
-
text: "Text explaining what is successful",
|
87
|
+
size: "status_size",
|
88
|
+
title: "Success!",
|
89
|
+
text: "Text explaining what is successful",
|
90
90
|
}) do %>
|
91
91
|
<%= pb_rails("dialog/dialog_footer") do %>
|
92
92
|
<%= pb_rails("flex", props: { spacing:"between", padding_x:"md", padding_bottom:"md", padding: "sm" }) do %>
|
@@ -83,8 +83,8 @@ const DialogStatus = () => {
|
|
83
83
|
|
84
84
|
return (
|
85
85
|
<div>
|
86
|
-
<Flex
|
87
|
-
rowGap="xs"
|
86
|
+
<Flex
|
87
|
+
rowGap="xs"
|
88
88
|
wrap
|
89
89
|
>
|
90
90
|
<Button
|
@@ -117,7 +117,7 @@ const DialogStatus = () => {
|
|
117
117
|
>
|
118
118
|
{"Success Status"}
|
119
119
|
</Button>
|
120
|
-
<Button
|
120
|
+
<Button
|
121
121
|
marginRight="md"
|
122
122
|
onClick={toggleErrorAlert}
|
123
123
|
>
|
@@ -152,6 +152,7 @@ const DialogStatus = () => {
|
|
152
152
|
<Button
|
153
153
|
onClick={dialog.toggle}
|
154
154
|
paddingRight="xl"
|
155
|
+
variant={dialog.status == "delete" ? "danger" : "primary"}
|
155
156
|
>
|
156
157
|
{dialog.buttonOneText}
|
157
158
|
</Button>
|
@@ -21,15 +21,6 @@
|
|
21
21
|
]
|
22
22
|
%>
|
23
23
|
|
24
|
-
<%
|
25
|
-
example_typeahead_options = [
|
26
|
-
{ label: 'Orange', value: '#FFA500' },
|
27
|
-
{ label: 'Red', value: '#FF0000' },
|
28
|
-
{ label: 'Green', value: '#00FF00' },
|
29
|
-
{ label: 'Blue', value: '#0000FF' },
|
30
|
-
]
|
31
|
-
%>
|
32
|
-
|
33
24
|
<% treeData = [{
|
34
25
|
label: "Power Home Remodeling",
|
35
26
|
value: "Power Home Remodeling",
|
@@ -97,9 +88,7 @@
|
|
97
88
|
}] %>
|
98
89
|
|
99
90
|
<%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
|
100
|
-
<%= form.typeahead :
|
101
|
-
<%= form.typeahead :example_typeahead_validation, props: { options: example_typeahead_options, pills: true, label: "Example Typeahead (React Rendered)", placeholder: "Search for a user", required: true, validation: { message: "Please select a color." } } %>
|
102
|
-
<%= form.typeahead :example_typeahead_validation_2, props: { options: example_typeahead_options, pills: true, label: "Example Typeahead 2 (React Rendered)", placeholder: "Search for a user", required: true } %>
|
91
|
+
<%= form.typeahead :example_typeahead_validation, props: { data: { typeahead_example2: true, user: {} }, label: true, placeholder: "Search for a user", required: true, validation: { message: "Please select a user." } } %>
|
103
92
|
<%= form.text_field :example_text_field_validation, props: { label: true, required: true } %>
|
104
93
|
<%= form.phone_number_field :example_phone_number_field_validation, props: { label: "Example phone field", hidden_inputs: true } %>
|
105
94
|
<%= form.email_field :example_email_field_validation, props: { label: true, required: true } %>
|
@@ -12,7 +12,6 @@
|
|
12
12
|
}
|
13
13
|
|
14
14
|
@mixin preview_tiptap_p {
|
15
|
-
margin: 1rem 0 0 0;
|
16
15
|
min-height: 1rem;
|
17
16
|
}
|
18
17
|
|
@@ -56,13 +55,9 @@
|
|
56
55
|
}
|
57
56
|
|
58
57
|
@mixin preview_tiptap_blockquote {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
margin: 1rem 0 0 0;
|
63
|
-
p {
|
64
|
-
margin: 0;
|
65
|
-
}
|
58
|
+
border-left: 3px solid $text_lt_lighter;
|
59
|
+
margin: 1.5rem 0;
|
60
|
+
padding-left: 1rem;
|
66
61
|
}
|
67
62
|
|
68
63
|
@mixin preview_tiptap_h1 {
|
@@ -70,7 +65,6 @@
|
|
70
65
|
line-height: $text_larger;
|
71
66
|
font-weight: $bolder;
|
72
67
|
letter-spacing: $lspace_tight;
|
73
|
-
margin: 2.1rem 0 0 0;
|
74
68
|
}
|
75
69
|
|
76
70
|
@mixin preview_tiptap_h2 {
|
@@ -78,7 +72,6 @@
|
|
78
72
|
line-height: $text_larger;
|
79
73
|
font-weight: $bolder;
|
80
74
|
letter-spacing: $lspace_tight;
|
81
|
-
margin: 1.9rem 0 0 0;
|
82
75
|
}
|
83
76
|
|
84
77
|
@mixin preview_tiptap_h3 {
|
@@ -86,7 +79,6 @@
|
|
86
79
|
line-height: $text_large;
|
87
80
|
font-weight: $bolder;
|
88
81
|
letter-spacing: $lspace_tight;
|
89
|
-
margin: 1.7rem 0 0 0;
|
90
82
|
}
|
91
83
|
|
92
84
|
@mixin preview_tiptap_smaller_headings {
|
@@ -94,7 +86,6 @@
|
|
94
86
|
line-height: $text_base;
|
95
87
|
letter-spacing: $lspace_tight;
|
96
88
|
font-weight: $bolder;
|
97
|
-
margin: 1rem 0 0 0;
|
98
89
|
}
|
99
90
|
|
100
91
|
@mixin preview_tiptap_hr {
|
@@ -110,7 +101,6 @@
|
|
110
101
|
}
|
111
102
|
|
112
103
|
@mixin preview_tiptap_ol {
|
113
|
-
margin: 1rem 0 0 0;
|
114
104
|
padding-left: $space_md;
|
115
105
|
list-style: decimal;
|
116
106
|
li {
|
@@ -140,10 +140,14 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
|
|
140
140
|
formattedValue = value
|
141
141
|
}
|
142
142
|
|
143
|
+
const errorId = error ? `${id}-error` : undefined
|
144
|
+
|
143
145
|
const textInput = (
|
144
146
|
childInput ? React.cloneElement(children, { className: "text_input" }) :
|
145
147
|
(<input
|
146
148
|
{...domSafeProps(props)}
|
149
|
+
aria-describedby={errorId}
|
150
|
+
aria-invalid={!!error}
|
147
151
|
autoComplete={typeof autoComplete === "string" ? autoComplete : ( autoComplete ? undefined : "off" )}
|
148
152
|
className="text_input"
|
149
153
|
disabled={disabled}
|
@@ -202,16 +206,20 @@ const TextInput = (props: TextInputProps, ref: React.LegacyRef<HTMLInputElement>
|
|
202
206
|
{...htmlProps}
|
203
207
|
className={css}
|
204
208
|
>
|
205
|
-
{label &&
|
206
|
-
<
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
209
|
+
{label && (
|
210
|
+
<label htmlFor={id}>
|
211
|
+
<Caption className="pb_text_input_kit_label"
|
212
|
+
text={label}
|
213
|
+
/>
|
214
|
+
</label>
|
215
|
+
)}
|
211
216
|
<div className={`${addOnCss} text_input_wrapper`}>
|
212
217
|
{render}
|
213
218
|
|
214
219
|
{error && <Body
|
220
|
+
aria={{ atomic: "true", live: "polite" }}
|
221
|
+
htmlOptions={{ role: "alert" }}
|
222
|
+
id={errorId}
|
215
223
|
status="negative"
|
216
224
|
text={error}
|
217
225
|
variant={null}
|
@@ -9,23 +9,27 @@
|
|
9
9
|
|
10
10
|
<%= pb_rails("text_input", props: {
|
11
11
|
label: "Last Name",
|
12
|
-
placeholder: "Enter last name"
|
12
|
+
placeholder: "Enter last name",
|
13
|
+
id: "last-name"
|
13
14
|
}) %>
|
14
15
|
|
15
16
|
<%= pb_rails("text_input", props: {
|
16
17
|
label: "Phone Number",
|
17
18
|
type: "phone",
|
18
|
-
placeholder: "Enter phone number"
|
19
|
+
placeholder: "Enter phone number",
|
20
|
+
id: "phone"
|
19
21
|
}) %>
|
20
22
|
|
21
23
|
<%= pb_rails("text_input", props: {
|
22
24
|
label: "Email Address",
|
23
25
|
type: "email",
|
24
|
-
placeholder: "Enter email address"
|
26
|
+
placeholder: "Enter email address",
|
27
|
+
id: "email"
|
25
28
|
}) %>
|
26
29
|
|
27
30
|
<%= pb_rails("text_input", props: {
|
28
31
|
label: "Zip Code",
|
29
32
|
type: "number",
|
30
|
-
placeholder: "Enter zip code"
|
33
|
+
placeholder: "Enter zip code",
|
34
|
+
id: "zip"
|
31
35
|
}) %>
|
@@ -38,6 +38,7 @@ const TextInputDefault = (props) => {
|
|
38
38
|
{...props}
|
39
39
|
/>
|
40
40
|
<TextInput
|
41
|
+
id="last-name"
|
41
42
|
label="Last Name"
|
42
43
|
name="lastName"
|
43
44
|
onChange={handleOnChangeFormField}
|
@@ -46,6 +47,7 @@ const TextInputDefault = (props) => {
|
|
46
47
|
{...props}
|
47
48
|
/>
|
48
49
|
<TextInput
|
50
|
+
id="phone"
|
49
51
|
label="Phone Number"
|
50
52
|
name="phone"
|
51
53
|
onChange={handleOnChangeFormField}
|
@@ -55,6 +57,7 @@ const TextInputDefault = (props) => {
|
|
55
57
|
{...props}
|
56
58
|
/>
|
57
59
|
<TextInput
|
60
|
+
id="email"
|
58
61
|
label="Email Address"
|
59
62
|
name="email"
|
60
63
|
onChange={handleOnChangeFormField}
|
@@ -64,6 +67,7 @@ const TextInputDefault = (props) => {
|
|
64
67
|
{...props}
|
65
68
|
/>
|
66
69
|
<TextInput
|
70
|
+
id="zip"
|
67
71
|
label="Zip Code"
|
68
72
|
name="zip"
|
69
73
|
onChange={handleOnChangeFormField}
|
@@ -84,6 +88,7 @@ const TextInputDefault = (props) => {
|
|
84
88
|
<br />
|
85
89
|
|
86
90
|
<TextInput
|
91
|
+
id="first-name"
|
87
92
|
label="First Name"
|
88
93
|
onChange={handleOnChangeFirstName}
|
89
94
|
placeholder="Enter first name"
|
@@ -0,0 +1 @@
|
|
1
|
+
Add an `id` to your Text Input so that clicking the label will move focus directly to the input.
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<%= pb_content_tag(:div, id: nil ) do %>
|
2
2
|
<% if object.label.present? %>
|
3
|
+
<label for="<%= object.input_options[:id] || object.id %>" >
|
3
4
|
<%= pb_rails("caption", props: { text: object.label, dark: object.dark, classname: "pb_text_input_kit_label" }) %>
|
5
|
+
</label>
|
4
6
|
<% end %>
|
5
7
|
<%= content_tag(:div, class: "#{add_on_class} text_input_wrapper") do %>
|
6
8
|
<% if content.present? %>
|
@@ -15,7 +17,7 @@
|
|
15
17
|
<% else %>
|
16
18
|
<%= input_tag %>
|
17
19
|
<% end %>
|
18
|
-
<%= pb_rails("body", props: {dark: object.dark, status: "negative", text: object.error}) if object.error %>
|
20
|
+
<%= pb_rails("body", props: {dark: object.dark, status: "negative", text: object.error, id: object.error_id, aria: { atomic: "true", live: "polite" }, html_options: { role: "alert" }}) if object.error %>
|
19
21
|
<% end %>
|
20
22
|
<% end %>
|
21
23
|
|
@@ -64,10 +64,16 @@ module Playbook
|
|
64
64
|
"#{object.id}-sanitized" if id.present?
|
65
65
|
end
|
66
66
|
|
67
|
+
def error_id
|
68
|
+
"#{id}-error" if error.present?
|
69
|
+
end
|
70
|
+
|
67
71
|
private
|
68
72
|
|
69
73
|
def all_input_options
|
70
74
|
{
|
75
|
+
'aria-describedby': error.present? ? error_id : nil,
|
76
|
+
'aria-invalid': error.present?,
|
71
77
|
autocomplete: autocomplete == true ? nil : (autocomplete.presence || "off"),
|
72
78
|
class: "text_input #{input_options.dig(:classname) || ''}",
|
73
79
|
data: validation_data,
|
@@ -53,8 +53,6 @@ type TypeaheadProps = {
|
|
53
53
|
pillColor?: "primary" | "neutral" | "success" | "warning" | "error" | "info" | "data_1" | "data_2" | "data_3" | "data_4" | "data_5" | "data_6" | "data_7" | "data_8" | "windows" | "siding" | "roofing" | "doors" | "gutters" | "solar" | "insulation" | "accessories",
|
54
54
|
onChange?: any,
|
55
55
|
optionsByContext?: Record<string, Array<{ label: string; value?: string }>>
|
56
|
-
required?: boolean,
|
57
|
-
validation?: { message: string },
|
58
56
|
searchContextSelector?: string,
|
59
57
|
clearOnContextChange?: boolean,
|
60
58
|
preserveSearchInput?: boolean,
|
@@ -96,16 +94,12 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
96
94
|
onChange,
|
97
95
|
optionsByContext = {},
|
98
96
|
searchContextSelector,
|
99
|
-
required = false,
|
100
|
-
validation,
|
101
97
|
clearOnContextChange = false,
|
102
98
|
preserveSearchInput = false, // Default to false to maintain backward compatibility
|
103
99
|
...props
|
104
100
|
}: TypeaheadProps) => {
|
105
101
|
// State to manage the input value when preserveSearchInput is true
|
106
102
|
const [inputValue, setInputValue] = useState("")
|
107
|
-
// State to track if form has been submitted to control validation display for react rendered rails kit
|
108
|
-
const [formSubmitted, setFormSubmitted] = useState(false)
|
109
103
|
|
110
104
|
// If preserveSearchInput is true, we need to control the input value
|
111
105
|
const handleInputChange = preserveSearchInput
|
@@ -141,7 +135,6 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
141
135
|
|
142
136
|
const selectProps = {
|
143
137
|
cacheOptions: true,
|
144
|
-
required,
|
145
138
|
components: {
|
146
139
|
Control,
|
147
140
|
ClearIndicator,
|
@@ -177,27 +170,6 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
177
170
|
|
178
171
|
const [contextValue, setContextValue] = useState("")
|
179
172
|
|
180
|
-
// Add listener for form validation to track when validation should be shown (needed for react rendered rails kit)
|
181
|
-
useEffect(() => {
|
182
|
-
const handleInvalid = (event: Event) => {
|
183
|
-
const target = event.target as HTMLInputElement
|
184
|
-
const typeaheadContainer = target.closest('[data-pb-react-component="Typeahead"]')
|
185
|
-
|
186
|
-
if (typeaheadContainer) {
|
187
|
-
// Check if this invalid event is specifically for our typeahead by comparing names so we do not have to require ids
|
188
|
-
const invalidInputName = target.name || target.getAttribute('name')
|
189
|
-
if (invalidInputName === name) {
|
190
|
-
setFormSubmitted(true)
|
191
|
-
}
|
192
|
-
}
|
193
|
-
}
|
194
|
-
document.addEventListener('invalid', handleInvalid, true)
|
195
|
-
|
196
|
-
return () => {
|
197
|
-
document.removeEventListener('invalid', handleInvalid, true)
|
198
|
-
}
|
199
|
-
}, [name])
|
200
|
-
|
201
173
|
// Add listener for clearing
|
202
174
|
useEffect(() => {
|
203
175
|
const handleClear = () => {
|
@@ -258,11 +230,6 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
258
230
|
}
|
259
231
|
}
|
260
232
|
|
261
|
-
// Reset form submitted state when a selection is made (this is all for react rendered rails kit)
|
262
|
-
if (action === 'select-option') {
|
263
|
-
setFormSubmitted(false)
|
264
|
-
}
|
265
|
-
|
266
233
|
// If a value is selected and we're preserving input on blur, clear the input
|
267
234
|
if (action === 'select-option' && preserveSearchInput) {
|
268
235
|
setInputValue('')
|
@@ -301,11 +268,6 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
301
268
|
|
302
269
|
const inlineClass = selectProps.inline ? 'inline' : null
|
303
270
|
|
304
|
-
const shouldShowValidationError = required &&
|
305
|
-
formSubmitted
|
306
|
-
|
307
|
-
const errorDisplay = error || (shouldShowValidationError ? validation?.message || "Please fill out this field." : "")
|
308
|
-
|
309
271
|
return (
|
310
272
|
<div
|
311
273
|
{...dataProps}
|
@@ -314,7 +276,7 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
314
276
|
>
|
315
277
|
<Tag
|
316
278
|
classNamePrefix="typeahead-kit-select"
|
317
|
-
error={
|
279
|
+
error={error}
|
318
280
|
isDisabled={disabled}
|
319
281
|
onChange={handleOnChange}
|
320
282
|
{...selectProps}
|
@@ -101,8 +101,6 @@ module Playbook
|
|
101
101
|
plusIcon: plus_icon,
|
102
102
|
truncate: truncate,
|
103
103
|
wrapped: wrapped,
|
104
|
-
required: required,
|
105
|
-
validation: validation,
|
106
104
|
searchContextSelector: search_context_selector,
|
107
105
|
optionsByContext: options_by_context,
|
108
106
|
clearOnContextChange: clear_on_context_change,
|