playbook_ui 14.11.1.pre.alpha.PLAY17445539 → 14.11.1.pre.alpha.hfhbrakemanplaybook5370
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_sort_control.md +2 -2
- data/app/pb_kits/playbook/pb_button/button.html.erb +3 -2
- data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +6 -1
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +6 -2
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_default_date.md +1 -1
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.html.erb +9 -3
- data/app/pb_kits/playbook/pb_draggable/docs/example.yml +0 -1
- data/app/pb_kits/playbook/pb_drawer/_drawer.scss +177 -154
- data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +264 -162
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +45 -3
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +1 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.jsx +16 -9
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +19 -44
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.md +3 -21
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +21 -16
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.jsx +19 -2
- data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -2
- data/app/pb_kits/playbook/pb_drawer/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_drawer/drawer.test.jsx +5 -5
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.md +1 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +12 -7
- data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +14 -9
- data/app/pb_kits/playbook/pb_dropdown/dropdown_option.html.erb +11 -6
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +14 -8
- data/app/pb_kits/playbook/pb_list/item.html.erb +8 -30
- data/app/pb_kits/playbook/pb_list/item.rb +0 -7
- data/app/pb_kits/playbook/pb_list/list.html.erb +11 -31
- data/app/pb_kits/playbook/pb_list/list.rb +0 -4
- data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.tsx +1 -6
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +12 -30
- data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +1 -3
- data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +0 -3
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +1 -20
- data/app/pb_kits/playbook/pb_radio/_radio.scss +8 -12
- data/app/pb_kits/playbook/pb_radio/docs/_radio_custom_children.jsx +3 -8
- data/app/pb_kits/playbook/pb_selectable_list/selectable_list.html.erb +3 -17
- data/app/pb_kits/playbook/pb_selectable_list/selectable_list.rb +0 -3
- data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.html.erb +4 -11
- data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.rb +0 -3
- data/app/pb_kits/playbook/pb_table/_table.tsx +3 -2
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_rails.md +2 -2
- data/app/pb_kits/playbook/pb_table/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_table/index.ts +34 -93
- data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +5 -6
- data/app/pb_kits/playbook/pb_table/table.html.erb +1 -1
- data/app/pb_kits/playbook/pb_table/table.rb +2 -17
- data/app/pb_kits/playbook/pb_timeline/_timeline.scss +30 -30
- data/dist/chunks/{_typeahead-vFuUQM5F.js → _typeahead-BNULwihE.js} +2 -2
- data/dist/chunks/_weekday_stacked-BKWemDAe.js +45 -0
- data/dist/chunks/{lib-OFT985dg.js → lib-B7sgJtGS.js} +2 -2
- data/dist/chunks/{pb_form_validation-CrsXd1-Y.js → pb_form_validation-C5Cc0-1v.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/version.rb +1 -1
- metadata +6 -21
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.md +0 -5
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.html.erb +0 -38
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.md +0 -3
- data/app/pb_kits/playbook/pb_drawer/context.ts +0 -11
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_behavior.jsx +0 -38
- data/app/pb_kits/playbook/pb_drawer/hooks/useBreakpoint.tsx +0 -73
- data/app/pb_kits/playbook/pb_drawer/hooks/useDrawerAnimation.tsx +0 -21
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.html.erb +0 -15
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.jsx +0 -24
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.md +0 -1
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns.html.erb +0 -74
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns_rails.md +0 -3
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns.html.erb +0 -74
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns_rails.md +0 -3
- data/app/pb_kits/playbook/pb_table/utilities/addDataTitle.ts +0 -22
- data/dist/chunks/_weekday_stacked-DG3A22sS.js +0 -45
@@ -35,7 +35,6 @@ type PhoneNumberInputProps = {
|
|
35
35
|
preferredCountries?: string[],
|
36
36
|
required?: boolean,
|
37
37
|
value?: string,
|
38
|
-
formatAsYouType?: boolean,
|
39
38
|
}
|
40
39
|
|
41
40
|
enum ValidationError {
|
@@ -88,7 +87,6 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
88
87
|
required = false,
|
89
88
|
preferredCountries = [],
|
90
89
|
value = "",
|
91
|
-
formatAsYouType = false,
|
92
90
|
} = props
|
93
91
|
|
94
92
|
const ariaProps = buildAriaProps(aria)
|
@@ -101,8 +99,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
101
99
|
)
|
102
100
|
|
103
101
|
const inputRef = useRef<HTMLInputElement>()
|
104
|
-
const itiRef = useRef<any>(null);
|
105
102
|
const [inputValue, setInputValue] = useState(value)
|
103
|
+
const [itiInit, setItiInit] = useState<any>()
|
106
104
|
const [error, setError] = useState(props.error)
|
107
105
|
const [dropDownIsOpen, setDropDownIsOpen] = useState(false)
|
108
106
|
const [selectedData, setSelectedData] = useState()
|
@@ -132,12 +130,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
132
130
|
}
|
133
131
|
})
|
134
132
|
|
135
|
-
const unformatNumber = (formattedNumber: any) => {
|
136
|
-
return formattedNumber.replace(/\D/g, "")
|
137
|
-
}
|
138
|
-
|
139
133
|
const showFormattedError = (reason = '') => {
|
140
|
-
const countryName =
|
134
|
+
const countryName = itiInit.getSelectedCountryData().name
|
141
135
|
const reasonText = reason.length > 0 ? ` (${reason})` : ''
|
142
136
|
setError(`Invalid ${countryName} phone number${reasonText}`)
|
143
137
|
return true
|
@@ -195,12 +189,12 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
195
189
|
}
|
196
190
|
|
197
191
|
const validateErrors = () => {
|
198
|
-
if (
|
199
|
-
if (validateOnlyNumbers(
|
200
|
-
if (validateTooLongNumber(
|
201
|
-
if (validateTooShortNumber(
|
202
|
-
if (validateUnhandledError(
|
203
|
-
if (validateMissingAreaCode(
|
192
|
+
if (itiInit) isValid(itiInit.isValidNumber())
|
193
|
+
if (validateOnlyNumbers(itiInit)) return
|
194
|
+
if (validateTooLongNumber(itiInit)) return
|
195
|
+
if (validateTooShortNumber(itiInit)) return
|
196
|
+
if (validateUnhandledError(itiInit)) return
|
197
|
+
if (validateMissingAreaCode(itiInit)) return
|
204
198
|
}
|
205
199
|
|
206
200
|
const getCurrentSelectedData = (itiInit: any, inputValue: string) => {
|
@@ -209,16 +203,10 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
209
203
|
|
210
204
|
const handleOnChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
|
211
205
|
setInputValue(evt.target.value)
|
212
|
-
|
213
|
-
if (formatAsYouType) {
|
214
|
-
const formattedPhoneNumberData = getCurrentSelectedData(itiRef.current, evt.target.value)
|
215
|
-
phoneNumberData = {...formattedPhoneNumberData, number: unformatNumber(formattedPhoneNumberData.number)}
|
216
|
-
} else {
|
217
|
-
phoneNumberData = getCurrentSelectedData(itiRef.current, evt.target.value)
|
218
|
-
}
|
206
|
+
const phoneNumberData = getCurrentSelectedData(itiInit, evt.target.value)
|
219
207
|
setSelectedData(phoneNumberData)
|
220
208
|
onChange(phoneNumberData)
|
221
|
-
isValid(
|
209
|
+
isValid(itiInit.isValidNumber())
|
222
210
|
}
|
223
211
|
|
224
212
|
// Separating Concerns as React Docs Recommend
|
@@ -242,11 +230,9 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
242
230
|
onlyCountries,
|
243
231
|
countrySearch: false,
|
244
232
|
fixDropdownWidth: false,
|
245
|
-
formatAsYouType:
|
233
|
+
formatAsYouType: false,
|
246
234
|
})
|
247
235
|
|
248
|
-
itiRef.current = telInputInit;
|
249
|
-
|
250
236
|
inputRef.current.addEventListener("countrychange", (evt: Event) => {
|
251
237
|
const phoneNumberData = getCurrentSelectedData(telInputInit, (evt.target as HTMLInputElement).value)
|
252
238
|
setSelectedData(phoneNumberData)
|
@@ -257,11 +243,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
257
243
|
inputRef.current.addEventListener("open:countrydropdown", () => setDropDownIsOpen(true))
|
258
244
|
inputRef.current.addEventListener("close:countrydropdown", () => setDropDownIsOpen(false))
|
259
245
|
|
260
|
-
|
261
|
-
inputRef.current?.addEventListener("input", (evt) => {
|
262
|
-
handleOnChange(evt as unknown as React.ChangeEvent<HTMLInputElement>);
|
263
|
-
});
|
264
|
-
}
|
246
|
+
setItiInit(telInputInit)
|
265
247
|
}, [])
|
266
248
|
|
267
249
|
let textInputProps: {[key: string]: any} = {
|
@@ -8,12 +8,10 @@ examples:
|
|
8
8
|
- phone_number_input_validation: Form Validation
|
9
9
|
- phone_number_input_clear_field: Clearing the Input Field
|
10
10
|
- phone_number_input_access_input_element: Accessing the Input Element
|
11
|
-
- phone_number_input_format: Format as You Type
|
12
11
|
|
13
12
|
rails:
|
14
13
|
- phone_number_input_default: Default
|
15
14
|
- phone_number_input_preferred_countries: Preferred Countries
|
16
15
|
- phone_number_input_initial_country: Initial Country
|
17
16
|
- phone_number_input_only_countries: Limited Countries
|
18
|
-
- phone_number_input_validation: Form Validation
|
19
|
-
- phone_number_input_format: Format as You Type
|
17
|
+
- phone_number_input_validation: Form Validation
|
@@ -5,4 +5,3 @@ export { default as PhoneNumberInputOnlyCountries } from './_phone_number_input_
|
|
5
5
|
export { default as PhoneNumberInputValidation } from './_phone_number_input_validation'
|
6
6
|
export { default as PhoneNumberInputClearField } from './_phone_number_input_clear_field'
|
7
7
|
export { default as PhoneNumberInputAccessInputElement } from './_phone_number_input_access_input_element'
|
8
|
-
export { default as PhoneNumberInputFormat } from './_phone_number_input_format'
|
@@ -21,8 +21,6 @@ module Playbook
|
|
21
21
|
default: ""
|
22
22
|
prop :value, type: Playbook::Props::String,
|
23
23
|
default: ""
|
24
|
-
prop :format_as_you_type, type: Playbook::Props::Boolean,
|
25
|
-
default: false
|
26
24
|
|
27
25
|
def classname
|
28
26
|
generate_classname("pb_phone_number_input")
|
@@ -34,7 +32,6 @@ module Playbook
|
|
34
32
|
dark: dark,
|
35
33
|
disabled: disabled,
|
36
34
|
error: error,
|
37
|
-
formatAsYouType: format_as_you_type,
|
38
35
|
initialCountry: initial_country,
|
39
36
|
label: label,
|
40
37
|
name: name,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import React from "react";
|
2
|
-
import { render, screen
|
2
|
+
import { render, screen } from "../utilities/test-utils";
|
3
3
|
import PhoneNumberInput from "./_phone_number_input";
|
4
4
|
|
5
5
|
const testId = "phoneNumberInput";
|
@@ -120,22 +120,3 @@ test("should trigger callback", () => {
|
|
120
120
|
|
121
121
|
expect(handleOnValidate).toBeCalledWith(true)
|
122
122
|
});
|
123
|
-
|
124
|
-
test("should format phone number as '555-555-5555' with formatAsYouType and 'us' country", () => {
|
125
|
-
const props = {
|
126
|
-
initialCountry: 'us',
|
127
|
-
formatAsYouType: true,
|
128
|
-
id: testId,
|
129
|
-
};
|
130
|
-
|
131
|
-
render(<PhoneNumberInput {...props} />);
|
132
|
-
|
133
|
-
const input = screen.getByRole("textbox");
|
134
|
-
|
135
|
-
act(() => {
|
136
|
-
input.value = "5555555555";
|
137
|
-
input.dispatchEvent(new Event('input', { bubbles: true }));
|
138
|
-
});
|
139
|
-
|
140
|
-
expect(input.value).toBe("555-555-5555");
|
141
|
-
});
|
@@ -4,7 +4,7 @@
|
|
4
4
|
@import "../pb_body/body";
|
5
5
|
@import "../tokens/transition";
|
6
6
|
|
7
|
-
[class^=
|
7
|
+
[class^=pb_radio_kit] {
|
8
8
|
display: inline-flex;
|
9
9
|
cursor: pointer;
|
10
10
|
|
@@ -16,11 +16,10 @@
|
|
16
16
|
border-radius: 1000px;
|
17
17
|
border: 2px solid $border_light;
|
18
18
|
margin-right: $space_xs;
|
19
|
-
transition: background $transition_default ease,
|
20
|
-
box-shadow $transition_default ease, border-color $transition_default ease;
|
19
|
+
transition: background $transition_default ease, box-shadow $transition_default ease, border-color $transition_default ease;
|
21
20
|
}
|
22
21
|
|
23
|
-
@media (hover:
|
22
|
+
@media (hover:hover) {
|
24
23
|
&:hover .pb_radio_button {
|
25
24
|
background-color: $bg_light;
|
26
25
|
border-color: $border_light;
|
@@ -53,14 +52,14 @@
|
|
53
52
|
}
|
54
53
|
}
|
55
54
|
|
56
|
-
&:disabled:checked + .pb_radio_button
|
55
|
+
&:disabled:checked + .pb_radio_button{
|
57
56
|
cursor: not-allowed;
|
58
57
|
background-color: $white;
|
59
58
|
border: 6px solid $neutral;
|
60
59
|
}
|
61
60
|
}
|
62
61
|
|
63
|
-
&[class*=
|
62
|
+
&[class*=vertical] {
|
64
63
|
flex-direction: column;
|
65
64
|
align-items: center;
|
66
65
|
.pb_radio_button {
|
@@ -81,7 +80,7 @@
|
|
81
80
|
}
|
82
81
|
&:checked {
|
83
82
|
& ~ .pb_radio_button {
|
84
|
-
border: 6px solid $
|
83
|
+
border: 6px solid $primary;
|
85
84
|
}
|
86
85
|
}
|
87
86
|
|
@@ -104,10 +103,10 @@
|
|
104
103
|
}
|
105
104
|
}
|
106
105
|
|
107
|
-
@media (hover:
|
106
|
+
@media (hover:hover) {
|
108
107
|
&:hover {
|
109
108
|
.pb_radio_button {
|
110
|
-
background-color: rgba($white
|
109
|
+
background-color: rgba($white,.10);
|
111
110
|
border-color: $border_dark;
|
112
111
|
}
|
113
112
|
}
|
@@ -116,9 +115,6 @@
|
|
116
115
|
> .pb_radio_button {
|
117
116
|
border-color: $error_dark;
|
118
117
|
}
|
119
|
-
> .pb_body_kit_negative {
|
120
|
-
color: $error_dark;
|
121
|
-
}
|
122
118
|
}
|
123
119
|
}
|
124
120
|
&.error {
|
@@ -29,7 +29,6 @@ const RadioChildren = (props) => {
|
|
29
29
|
marginBottom="none"
|
30
30
|
minWidth="xs"
|
31
31
|
options={options}
|
32
|
-
{...props}
|
33
32
|
/>
|
34
33
|
</Radio>
|
35
34
|
<Radio
|
@@ -41,11 +40,10 @@ const RadioChildren = (props) => {
|
|
41
40
|
value="Typeahead"
|
42
41
|
{...props}
|
43
42
|
>
|
44
|
-
<Typeahead
|
43
|
+
<Typeahead
|
45
44
|
marginBottom="none"
|
46
45
|
minWidth="xs"
|
47
46
|
options={options}
|
48
|
-
{...props}
|
49
47
|
/>
|
50
48
|
</Radio>
|
51
49
|
<Radio
|
@@ -56,12 +54,9 @@ const RadioChildren = (props) => {
|
|
56
54
|
value="Typography"
|
57
55
|
{...props}
|
58
56
|
>
|
59
|
-
<Title
|
60
|
-
text="Custom Typography"
|
61
|
-
{...props}
|
62
|
-
/>
|
57
|
+
<Title text="Custom Typography" />
|
63
58
|
</Radio>
|
64
59
|
</div>
|
65
60
|
)
|
66
61
|
}
|
67
|
-
export default RadioChildren
|
62
|
+
export default RadioChildren
|
@@ -4,23 +4,9 @@
|
|
4
4
|
data: object.data,
|
5
5
|
id: object.id,
|
6
6
|
**combined_html_options) do %>
|
7
|
-
|
8
|
-
|
9
|
-
<%= pb_rails("
|
10
|
-
<%= pb_rails("list", props: {ordered: false}) do %>
|
11
|
-
<% object.items.each do |item| %>
|
12
|
-
<%= pb_rails("draggable/draggable_item", props: {drag_id: item[:drag_id]}) do %>
|
13
|
-
<%= pb_rails("selectable_list/selectable_list_item", props: item.merge(variant: object.variant, id: object.get_id(item), drag_id: item[:drag_id]) )%>
|
14
|
-
<% end %>
|
15
|
-
<% end %>
|
16
|
-
<% end %>
|
17
|
-
<% end %>
|
18
|
-
<% end %>
|
19
|
-
<% else %>
|
20
|
-
<%= pb_rails("list") do %>
|
21
|
-
<% object.items.each do |item| %>
|
22
|
-
<%= pb_rails("selectable_list/selectable_list_item", props: item.merge(variant: object.variant, id: object.get_id(item)) )%>
|
23
|
-
<% end %>
|
7
|
+
<%= pb_rails("list") do %>
|
8
|
+
<% object.items.each do |item| %>
|
9
|
+
<%= pb_rails("selectable_list/selectable_list_item", props: item.merge(variant: object.variant, id: object.get_id(item)) )%>
|
24
10
|
<% end %>
|
25
11
|
<% end %>
|
26
12
|
<% end %>
|
@@ -4,13 +4,6 @@
|
|
4
4
|
data: object.data,
|
5
5
|
id: object.id,
|
6
6
|
**combined_html_options) do %>
|
7
|
-
<% if object.drag_id && object.drag_handle %>
|
8
|
-
<span style="vertical-align: middle;">
|
9
|
-
<%= pb_rails("body") do %>
|
10
|
-
<svg width="auto" height="auto" viewBox="0 0 31 25" fill="none" xmlns="http://www.w3.org/2000/svg" color="currentColor" class="pb_custom_icon svg-inline--fa vertical_align_middle svg_fw"><path d="M12.904 6.355a1.48 1.48 0 01-1.5-1.5c0-.796.656-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5zm0 7.5a1.48 1.48 0 01-1.5-1.5c0-.796.656-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5zm1.5 6c0 .844-.703 1.5-1.5 1.5a1.48 1.48 0 01-1.5-1.5c0-.796.656-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5zm4.5-13.5a1.48 1.48 0 01-1.5-1.5c0-.796.657-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5zm1.5 6c0 .844-.703 1.5-1.5 1.5a1.48 1.48 0 01-1.5-1.5c0-.796.657-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5zm-1.5 9a1.48 1.48 0 01-1.5-1.5c0-.796.657-1.5 1.5-1.5.797 0 1.5.704 1.5 1.5 0 .844-.703 1.5-1.5 1.5z" fill="#242B42"></path></svg>
|
11
|
-
<% end %>
|
12
|
-
</span>
|
13
|
-
<% end %>
|
14
7
|
<% if object.variant == "radio"%>
|
15
8
|
<%= pb_rails("radio", props: { text: object.text, checked: object.checked, input_options: object.input_options } ) %>
|
16
9
|
<% if content.present? %>
|
@@ -26,10 +19,10 @@
|
|
26
19
|
<% if object.variant == "checkbox"%>
|
27
20
|
<script>
|
28
21
|
var checkboxElement = document.querySelector("#<%=object.id%> input[type=checkbox]")
|
29
|
-
|
22
|
+
|
30
23
|
checkboxElement.addEventListener("change", (evt) => {
|
31
24
|
var listItemElement = document.querySelector("#<%=object.id%>")
|
32
|
-
|
25
|
+
|
33
26
|
if (evt.target.checked) {
|
34
27
|
listItemElement.classList.add("checked_item");
|
35
28
|
} else {
|
@@ -41,9 +34,9 @@
|
|
41
34
|
<script>
|
42
35
|
var radioElement = document.querySelector("#<%=object.id%> input[type=radio]")
|
43
36
|
|
44
|
-
radioElement.addEventListener("change", () => {
|
37
|
+
radioElement.addEventListener("change", () => {
|
45
38
|
var radios = radioElement.closest("ul").querySelectorAll("input[type=radio]")
|
46
|
-
|
39
|
+
|
47
40
|
radios.forEach((radio) => {
|
48
41
|
if (radio.checked) {
|
49
42
|
radio.closest("li").classList.add("checked_item");
|
@@ -6,9 +6,6 @@ module Playbook
|
|
6
6
|
prop :tabindex
|
7
7
|
prop :checked, type: Playbook::Props::Boolean,
|
8
8
|
default: false
|
9
|
-
prop :drag_handle, type: Playbook::Props::Boolean,
|
10
|
-
default: true
|
11
|
-
prop :drag_id, type: Playbook::Props::String
|
12
9
|
prop :name, type: Playbook::Props::String
|
13
10
|
prop :text, type: Playbook::Props::String
|
14
11
|
prop :value, type: Playbook::Props::String
|
@@ -2,6 +2,7 @@ import React, { useEffect } from 'react'
|
|
2
2
|
import classnames from 'classnames'
|
3
3
|
import { buildAriaProps, buildDataProps, buildHtmlProps } from '../utilities/props'
|
4
4
|
import { globalProps, GlobalProps, globalInlineProps } from '../utilities/globalProps'
|
5
|
+
import PbTable from '.'
|
5
6
|
import {
|
6
7
|
TableHead,
|
7
8
|
TableHeader,
|
@@ -9,7 +10,6 @@ import {
|
|
9
10
|
TableRow,
|
10
11
|
TableCell,
|
11
12
|
} from "./subcomponents";
|
12
|
-
import { addDataTitle } from './utilities/addDataTitle'
|
13
13
|
|
14
14
|
type TableProps = {
|
15
15
|
aria?: { [key: string]: string },
|
@@ -196,7 +196,8 @@ const Table = (props: TableProps): React.ReactElement => {
|
|
196
196
|
}, [stickyRightColumn]);
|
197
197
|
|
198
198
|
useEffect(() => {
|
199
|
-
|
199
|
+
const instance = new PbTable()
|
200
|
+
instance.connect()
|
200
201
|
}, [])
|
201
202
|
|
202
203
|
return (
|
@@ -1,3 +1,3 @@
|
|
1
|
-
The `
|
1
|
+
The `stickyLeftColumn` prop expects an array of the column ids you want to be sticky. Make sure to add the corresponding id to the `<th>` and `<td>`.
|
2
2
|
|
3
|
-
Please ensure that unique ids are used for all columns across multiple tables. Using the same columns ids on multiple tables can lead to issues when using the `
|
3
|
+
Please ensure that unique ids are used for all columns across multiple tables. Using the same columns ids on multiple tables can lead to issues when using the `stickyLeftColumn`.
|
@@ -5,8 +5,6 @@ examples:
|
|
5
5
|
- table_lg: Large
|
6
6
|
- table_sticky: Sticky Header
|
7
7
|
- table_sticky_left_columns: Sticky Left Column
|
8
|
-
- table_sticky_right_columns: Sticky Right Column
|
9
|
-
- table_sticky_columns: Sticky Left and Right Columns
|
10
8
|
- table_header: Table Header
|
11
9
|
- table_alignment_row_rails: Row Alignment
|
12
10
|
- table_alignment_column_rails: Cell Alignment
|
@@ -1,67 +1,73 @@
|
|
1
1
|
import PbEnhancedElement from '../pb_enhanced_element'
|
2
2
|
|
3
|
-
const TABLE_WRAPPER_SELECTOR = "[data-pb-table-wrapper]";
|
4
|
-
|
5
3
|
export default class PbTable extends PbEnhancedElement {
|
6
|
-
stickyLeftColumns: string[] = [];
|
7
|
-
|
8
|
-
stickyRightColumnsReversed: string[] = [];
|
4
|
+
private stickyLeftColumns: string[] = [];
|
5
|
+
private handleStickyLeftColumnsRef: () => void;
|
9
6
|
|
10
7
|
static get selector(): string {
|
11
|
-
return
|
8
|
+
return '.table-responsive-collapse'
|
12
9
|
}
|
13
10
|
|
14
|
-
connect() {
|
15
|
-
|
11
|
+
connect(): void {
|
12
|
+
const tables = document.querySelectorAll('.table-responsive-collapse');
|
13
|
+
// Each Table
|
14
|
+
[].forEach.call(tables, (table: HTMLTableElement) => {
|
15
|
+
// Header Titles
|
16
16
|
const headers: string[] = [];
|
17
|
-
|
18
|
-
[].forEach.call(this.element.querySelectorAll('th'), (header: HTMLTableCellElement) => {
|
17
|
+
[].forEach.call(table.querySelectorAll('th'), (header: HTMLTableCellElement) => {
|
19
18
|
const colSpan = header.colSpan
|
20
19
|
for (let i = 0; i < colSpan; i++) {
|
21
20
|
headers.push(header.textContent.replace(/\r?\n|\r/, ''));
|
22
21
|
}
|
23
22
|
});
|
24
|
-
|
25
|
-
[].forEach.call(
|
23
|
+
// for each row in tbody
|
24
|
+
[].forEach.call(table.querySelectorAll('tbody tr'), (row: HTMLTableRowElement) => {
|
25
|
+
// for each cell
|
26
26
|
[].forEach.call(row.cells, (cell: HTMLTableCellElement, headerIndex: number) => {
|
27
|
+
// apply the attribute
|
27
28
|
cell.setAttribute('data-title', headers[headerIndex])
|
28
29
|
})
|
29
30
|
})
|
30
|
-
}
|
31
|
+
});
|
31
32
|
|
33
|
+
// New sticky columns logic
|
32
34
|
this.initStickyLeftColumns();
|
33
|
-
this.initStickyRightColumns();
|
34
35
|
}
|
35
36
|
|
36
|
-
initStickyLeftColumns() {
|
37
|
-
|
37
|
+
private initStickyLeftColumns(): void {
|
38
|
+
// Find tables with sticky-left-column class
|
39
|
+
const tables = document.querySelectorAll('.sticky-left-column');
|
38
40
|
|
39
|
-
|
41
|
+
tables.forEach((table) => {
|
42
|
+
// Extract sticky left column IDs by looking at the component's class
|
40
43
|
const classList = Array.from(table.classList);
|
41
|
-
const stickyColumnClass = classList.find(cls => cls.startsWith('sticky-left-columns-ids-'));
|
42
44
|
|
45
|
+
// Look for classes in the format sticky-left-column-{ids}
|
46
|
+
const stickyColumnClass = classList.find(cls => cls.startsWith('sticky-columns-'));
|
43
47
|
if (stickyColumnClass) {
|
48
|
+
// Extract the IDs from the class name
|
44
49
|
this.stickyLeftColumns = stickyColumnClass
|
45
|
-
|
46
|
-
|
50
|
+
.replace('sticky-columns-', '')
|
51
|
+
.split('-');
|
47
52
|
|
48
53
|
if (this.stickyLeftColumns.length > 0) {
|
49
54
|
setTimeout(() => {
|
55
|
+
this.handleStickyLeftColumnsRef = this.handleStickyLeftColumns.bind(this);
|
50
56
|
this.handleStickyLeftColumns();
|
51
|
-
window.addEventListener('resize',
|
57
|
+
window.addEventListener('resize', this.handleStickyLeftColumnsRef);
|
52
58
|
}, 10);
|
53
59
|
}
|
54
60
|
}
|
55
|
-
}
|
61
|
+
});
|
56
62
|
}
|
57
63
|
|
58
|
-
handleStickyLeftColumns() {
|
64
|
+
private handleStickyLeftColumns(): void {
|
59
65
|
let accumulatedWidth = 0;
|
60
66
|
|
61
67
|
this.stickyLeftColumns.forEach((colId, index) => {
|
62
68
|
const isLastColumn = index === this.stickyLeftColumns.length - 1;
|
63
|
-
const header =
|
64
|
-
const cells =
|
69
|
+
const header = document.querySelector(`th[id="${colId}"]`);
|
70
|
+
const cells = document.querySelectorAll(`td[id="${colId}"]`);
|
65
71
|
|
66
72
|
if (header) {
|
67
73
|
header.classList.add('sticky');
|
@@ -93,75 +99,10 @@ export default class PbTable extends PbEnhancedElement {
|
|
93
99
|
});
|
94
100
|
}
|
95
101
|
|
96
|
-
initStickyRightColumns() {
|
97
|
-
const table = this.element.querySelector('.sticky-right-column');
|
98
|
-
|
99
|
-
if (table) {
|
100
|
-
const classList = Array.from(table.classList);
|
101
|
-
const stickyColumnClass = classList.find(cls => cls.startsWith('sticky-right-columns-ids-'));
|
102
|
-
|
103
|
-
if (stickyColumnClass) {
|
104
|
-
this.stickyRightColumns = stickyColumnClass
|
105
|
-
.replace('sticky-right-columns-ids-', '')
|
106
|
-
.split('-');
|
107
|
-
this.stickyRightColumnsReversed = this.stickyRightColumns.reverse();
|
108
|
-
|
109
|
-
if (this.stickyRightColumns.length > 0) {
|
110
|
-
setTimeout(() => {
|
111
|
-
this.handleStickyRightColumns();
|
112
|
-
window.addEventListener('resize', () => this.handleStickyRightColumns());
|
113
|
-
}, 10);
|
114
|
-
}
|
115
|
-
}
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
handleStickyRightColumns() {
|
120
|
-
let accumulatedWidth = 0;
|
121
|
-
|
122
|
-
this.stickyRightColumnsReversed.forEach((colId, index) => {
|
123
|
-
const isLastColumn = index === this.stickyRightColumns.length - 1;
|
124
|
-
const header = this.element.querySelector(`th[id="${colId}"]`);
|
125
|
-
const cells = this.element.querySelectorAll(`td[id="${colId}"]`);
|
126
|
-
|
127
|
-
if (header) {
|
128
|
-
header.classList.add('sticky');
|
129
|
-
(header as HTMLElement).style.right = `${accumulatedWidth}px`;
|
130
|
-
|
131
|
-
if (!isLastColumn) {
|
132
|
-
header.classList.add('with-border-left');
|
133
|
-
header.classList.remove('sticky-right-shadow');
|
134
|
-
} else {
|
135
|
-
header.classList.remove('with-border-right');
|
136
|
-
header.classList.add('sticky-right-shadow');
|
137
|
-
}
|
138
|
-
|
139
|
-
accumulatedWidth += (header as HTMLElement).offsetWidth;
|
140
|
-
}
|
141
|
-
|
142
|
-
cells.forEach((cell) => {
|
143
|
-
cell.classList.add('sticky');
|
144
|
-
(cell as HTMLElement).style.right = `${accumulatedWidth - (header as HTMLElement).offsetWidth}px`;
|
145
|
-
|
146
|
-
if (!isLastColumn) {
|
147
|
-
cell.classList.add('with-border-left');
|
148
|
-
cell.classList.remove('sticky-right-shadow');
|
149
|
-
} else {
|
150
|
-
cell.classList.remove('with-border-left');
|
151
|
-
cell.classList.add('sticky-right-shadow');
|
152
|
-
}
|
153
|
-
});
|
154
|
-
});
|
155
|
-
}
|
156
|
-
|
157
102
|
// Cleanup method to remove event listener
|
158
|
-
disconnect() {
|
159
|
-
if (this.
|
160
|
-
window.removeEventListener('resize',
|
161
|
-
}
|
162
|
-
|
163
|
-
if (this.stickyRightColumns.length > 0) {
|
164
|
-
window.removeEventListener('resize', () => this.handleStickyRightColumns());
|
103
|
+
disconnect(): void {
|
104
|
+
if (this.handleStickyLeftColumnsRef) {
|
105
|
+
window.removeEventListener('resize', this.handleStickyLeftColumnsRef);
|
165
106
|
}
|
166
107
|
}
|
167
108
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
@import "../../tokens/screen_sizes";
|
2
|
-
@import "../../tokens/border_radius";
|
3
2
|
|
4
3
|
.table-responsive-scroll {
|
4
|
+
display: block;
|
5
5
|
overflow-x: scroll;
|
6
6
|
|
7
7
|
// hides duplicate scroll bar for those that see two (byproduct of repeated table-responsive-scroll class
|
@@ -27,12 +27,11 @@
|
|
27
27
|
// Responsive Styles
|
28
28
|
@media (max-width: 1600px) {
|
29
29
|
&[class*="table-responsive-scroll"] {
|
30
|
-
|
31
|
-
|
32
|
-
box-shadow: 1px 0 0 0px $border_light,
|
30
|
+
border-radius: 4px;
|
31
|
+
box-shadow: 1px 0 0 0px $border_light,
|
33
32
|
-1px 0 0 0px $border_light
|
34
|
-
|
35
|
-
|
33
|
+
}
|
34
|
+
|
36
35
|
&[class^=pb_table].table-sm.table-card thead tr th:first-child,
|
37
36
|
&[class^=pb_table].table-sm:not(.no-hover).table-card tbody tr td:first-child {
|
38
37
|
border-left-width: 0px;
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% responsive_class = nil %>
|
5
5
|
<% end %>
|
6
6
|
|
7
|
-
<%= content_tag(:div, class: responsive_class
|
7
|
+
<%= content_tag(:div, class: responsive_class) do %>
|
8
8
|
<% if object.tag == "table" %>
|
9
9
|
<%= content_tag(:table,
|
10
10
|
aria: object.aria,
|