playbook_ui 14.11.1.pre.alpha.PBNTR769sticky5359 → 14.11.1.pre.alpha.PBNTR7495495

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +18 -2
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +27 -5
  4. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +17 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +23 -1
  6. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +29 -6
  7. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +61 -4
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_sticky_header_responsive.jsx → _advanced_table_no_subrows.jsx} +4 -6
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.jsx +1 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.jsx +1 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.jsx +60 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.md +5 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions.jsx +78 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions.md +1 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header.jsx +53 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header.md +1 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.jsx +52 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.md +1 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_no_subrows.json +42 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_with_id.json +299 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +5 -1
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +5 -1
  23. data/app/pb_kits/playbook/pb_button/button.html.erb +2 -3
  24. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +1 -6
  25. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +2 -6
  26. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_default_date.md +1 -1
  27. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.html.erb +3 -9
  28. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.md +5 -0
  29. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.html.erb +38 -0
  30. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.md +3 -0
  31. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -0
  32. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +7 -12
  33. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +9 -14
  34. data/app/pb_kits/playbook/pb_dropdown/dropdown_option.html.erb +6 -11
  35. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +8 -14
  36. data/app/pb_kits/playbook/pb_list/item.html.erb +30 -8
  37. data/app/pb_kits/playbook/pb_list/item.rb +7 -0
  38. data/app/pb_kits/playbook/pb_list/list.html.erb +31 -11
  39. data/app/pb_kits/playbook/pb_list/list.rb +4 -0
  40. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +30 -12
  41. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.html.erb +15 -0
  42. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.jsx +24 -0
  43. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.md +1 -0
  44. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +3 -1
  45. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  46. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  47. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +20 -1
  48. data/app/pb_kits/playbook/pb_selectable_list/selectable_list.html.erb +17 -3
  49. data/app/pb_kits/playbook/pb_selectable_list/selectable_list.rb +3 -0
  50. data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.html.erb +11 -4
  51. data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.rb +3 -0
  52. data/app/pb_kits/playbook/pb_table/_table.tsx +2 -3
  53. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns.html.erb +74 -0
  54. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns_rails.md +3 -0
  55. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_rails.md +2 -2
  56. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns.html.erb +74 -0
  57. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns_rails.md +3 -0
  58. data/app/pb_kits/playbook/pb_table/docs/example.yml +2 -0
  59. data/app/pb_kits/playbook/pb_table/index.ts +93 -34
  60. data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +6 -5
  61. data/app/pb_kits/playbook/pb_table/table.html.erb +1 -1
  62. data/app/pb_kits/playbook/pb_table/table.rb +17 -2
  63. data/app/pb_kits/playbook/pb_table/utilities/addDataTitle.ts +22 -0
  64. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +30 -30
  65. data/dist/chunks/_typeahead-D_mMNEad.js +36 -0
  66. data/dist/chunks/_weekday_stacked-CGe59pJD.js +45 -0
  67. data/dist/chunks/{lib-B7sgJtGS.js → lib-OFT985dg.js} +2 -2
  68. data/dist/chunks/{pb_form_validation-C5Cc0-1v.js → pb_form_validation-CrsXd1-Y.js} +1 -1
  69. data/dist/chunks/vendor.js +1 -1
  70. data/dist/playbook-doc.js +1 -1
  71. data/dist/playbook-rails-react-bindings.js +1 -1
  72. data/dist/playbook-rails.js +1 -1
  73. data/dist/playbook.css +1 -1
  74. data/lib/playbook/version.rb +1 -1
  75. metadata +42 -7
  76. data/dist/chunks/_typeahead-BNULwihE.js +0 -36
  77. data/dist/chunks/_weekday_stacked-BKWemDAe.js +0 -45
@@ -11,6 +11,7 @@ examples:
11
11
  rails:
12
12
  - draggable_default_rails: Default
13
13
  - draggable_with_list_rails: Draggable with List Kit
14
+ - draggable_with_selectable_list_rails: Draggable with SelectableList Kit
14
15
  - draggable_with_cards_rails: Draggable with Cards
15
16
 
16
17
 
@@ -1,19 +1,14 @@
1
- <%= content_tag(:div,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.id,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
7
2
  <% if object.label.present? %>
8
3
  <%= pb_rails("caption", props: {text: object.label, margin_bottom:"xs"}) %>
9
4
  <% end %>
10
5
  <div class="dropdown_wrapper<%= error_class %>" style="position: relative">
11
- <input
12
- data-default-value="<%= input_default_value %>"
13
- id="dropdown-selected-option"
14
- name="<%= object.name %>"
15
- style="display: none"
16
- <%= object.required ? "required" : ""%>
6
+ <input
7
+ data-default-value="<%= input_default_value %>"
8
+ id="dropdown-selected-option"
9
+ name="<%= object.name %>"
10
+ style="display: none"
11
+ <%= object.required ? "required" : ""%>
17
12
  />
18
13
  <% if content.present? %>
19
14
  <%= content.presence %>
@@ -1,20 +1,15 @@
1
- <%= content_tag(:div,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.id,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
7
2
  <%= pb_rails("list", props: {ordered: false, borderless: false}) do %>
8
- <% if content.present? %>
3
+ <% if content.present? %>
9
4
  <%= content.presence %>
10
- <% else %>
5
+ <% else %>
11
6
  <%= pb_rails("list/item", props: {
12
- display: "flex",
13
- justify_content: "center",
14
- padding:"xs",
15
- }) do %>
7
+ display: "flex",
8
+ justify_content: "center",
9
+ padding:"xs",
10
+ }) do %>
16
11
  <%= pb_rails("body", props: {text: "No option"}) %>
17
12
  <% end %>
18
13
  <% end %>
19
- <% end %>
20
- <% end %>
14
+ <% end %>
15
+ <% end %>
@@ -1,15 +1,10 @@
1
- <%= content_tag(:div,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.option[:id],
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag(:div, id: object.option[:id]) do %>
7
2
  <%= pb_rails("list/item", props: {
8
- display: "flex",
9
- justify_content: "center",
10
- padding:"none",
3
+ display: "flex",
4
+ justify_content: "center",
5
+ padding:"none",
11
6
  cursor: "pointer"
12
- }) do %>
7
+ }) do %>
13
8
  <div class="dropdown_option_wrapper">
14
9
  <% if content.present? %>
15
10
  <%= content.presence %>
@@ -18,4 +13,4 @@
18
13
  <% end %>
19
14
  </div>
20
15
  <% end %>
21
- <% end %>
16
+ <% end %>
@@ -1,21 +1,16 @@
1
- <%= content_tag(:div,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.id,
6
- **combined_html_options) do %>
1
+ <%= pb_content_tag do %>
7
2
  <% if content.present? %>
8
3
  <div style="display: inline-block" tabindex="0" data-dropdown-custom-trigger>
9
4
  <%= content.presence %>
10
5
  </div>
11
6
  <% else %>
12
7
  <%= pb_rails("flex", props: {
13
- align: "center",
14
- border_radius:"lg",
15
- classname: object.trigger_wrapper_classes,
16
- cursor: "pointer",
17
- justify: "between",
18
- padding_x:"sm",
8
+ align: "center",
9
+ border_radius:"lg",
10
+ classname: object.trigger_wrapper_classes,
11
+ cursor: "pointer",
12
+ justify: "between",
13
+ padding_x:"sm",
19
14
  padding_y:"xs",
20
15
  html_options: {tabindex:"0"}
21
16
  }) do %>
@@ -23,7 +18,7 @@
23
18
  <%= pb_rails("flex", props: {align: "center"}) do %>
24
19
  <% if object.custom_display.present? %>
25
20
  <%= pb_rails("flex", props: {align: "center"}) do %>
26
- <div id="dropdown_trigger_custom_display" style="display: none;">
21
+ <div id="dropdown_trigger_custom_display" style="display: none;">
27
22
  <%= object.custom_display %>
28
23
  </div>
29
24
  <%= pb_rails("body", props: {text: object.default_display_placeholder, id: "dropdown_trigger_display"}) %>
@@ -40,4 +35,3 @@
40
35
  <% end %>
41
36
  <% end %>
42
37
  <% end %>
43
-
@@ -1,10 +1,32 @@
1
- <%= content_tag(:li,
2
- aria: object.aria,
3
- class: object.classname,
4
- data: object.data,
5
- id: object.id,
6
- tabindex: object.tabindex,
7
- **combined_html_options
8
- ) do %>
1
+ <% if object.draggable? %>
2
+ <%= pb_rails("draggable/draggable_item", props:{drag_id: object.drag_id}) do %>
3
+ <%= content_tag(:li,
4
+ aria: object.aria,
5
+ class: object.classname,
6
+ data: object.data,
7
+ id: object.id,
8
+ tabindex: object.tabindex,
9
+ **combined_html_options
10
+ ) do %>
11
+ <% if object.drag_handle %>
12
+ <span style="vertical-align: middle;">
13
+ <%= pb_rails("body") do %>
14
+ <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>
15
+ <% end %>
16
+ </span>
17
+ <% end %>
18
+ <%= content.presence %>
19
+ <% end %>
20
+ <% end %>
21
+ <% else %>
22
+ <%= content_tag(:li,
23
+ aria: object.aria,
24
+ class: object.classname,
25
+ data: object.data,
26
+ id: object.id,
27
+ tabindex: object.tabindex,
28
+ **combined_html_options
29
+ ) do %>
9
30
  <%= content.presence %>
31
+ <% end %>
10
32
  <% end %>
@@ -3,11 +3,18 @@
3
3
  module Playbook
4
4
  module PbList
5
5
  class Item < Playbook::KitBase
6
+ prop :drag_handle, type: Playbook::Props::Boolean,
7
+ default: true
8
+ prop :drag_id, type: Playbook::Props::String
6
9
  prop :tabindex
7
10
 
8
11
  def classname
9
12
  generate_classname("pb_item_kit")
10
13
  end
14
+
15
+ def draggable?
16
+ drag_id.present?
17
+ end
11
18
  end
12
19
  end
13
20
  end
@@ -1,13 +1,33 @@
1
- <%= content_tag(:div, class: object.list_classname) do %>
2
- <%= content_tag(:"#{object.ordered_class}",
3
- aria: object.aria,
4
- class: object.classname,
5
- data: object.data,
6
- id: object.id,
7
- role: object.role,
8
- tabindex: object.tabindex,
9
- **combined_html_options
10
- ) do %>
11
- <%= content.presence %>
1
+ <% if object.enable_drag %>
2
+ <%= pb_rails("draggable", props: {initial_items: object.items}) do %>
3
+ <%= pb_rails("draggable/draggable_container") do %>
4
+ <%= content_tag(:div, class: object.list_classname) do %>
5
+ <%= content_tag(:"#{object.ordered_class}",
6
+ aria: object.aria,
7
+ class: object.classname,
8
+ data: object.data,
9
+ id: object.id,
10
+ role: object.role,
11
+ tabindex: object.tabindex,
12
+ **combined_html_options
13
+ ) do %>
14
+ <%= content.presence %>
15
+ <% end %>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
19
+ <% else %>
20
+ <%= content_tag(:div, class: object.list_classname) do %>
21
+ <%= content_tag(:"#{object.ordered_class}",
22
+ aria: object.aria,
23
+ class: object.classname,
24
+ data: object.data,
25
+ id: object.id,
26
+ role: object.role,
27
+ tabindex: object.tabindex,
28
+ **combined_html_options
29
+ ) do %>
30
+ <%= content.presence %>
31
+ <% end %>
12
32
  <% end %>
13
33
  <% end %>
@@ -7,6 +7,10 @@ module Playbook
7
7
  default: false
8
8
  prop :dark, type: Playbook::Props::Boolean,
9
9
  default: false
10
+ prop :enable_drag, type: Playbook::Props::Boolean,
11
+ default: false
12
+ prop :items, type: Playbook::Props::Array,
13
+ default: []
10
14
  prop :layout, type: Playbook::Props::Enum,
11
15
  values: ["left", "right", ""],
12
16
  default: ""
@@ -35,6 +35,7 @@ type PhoneNumberInputProps = {
35
35
  preferredCountries?: string[],
36
36
  required?: boolean,
37
37
  value?: string,
38
+ formatAsYouType?: boolean,
38
39
  }
39
40
 
40
41
  enum ValidationError {
@@ -87,6 +88,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
87
88
  required = false,
88
89
  preferredCountries = [],
89
90
  value = "",
91
+ formatAsYouType = false,
90
92
  } = props
91
93
 
92
94
  const ariaProps = buildAriaProps(aria)
@@ -99,8 +101,8 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
99
101
  )
100
102
 
101
103
  const inputRef = useRef<HTMLInputElement>()
104
+ const itiRef = useRef<any>(null);
102
105
  const [inputValue, setInputValue] = useState(value)
103
- const [itiInit, setItiInit] = useState<any>()
104
106
  const [error, setError] = useState(props.error)
105
107
  const [dropDownIsOpen, setDropDownIsOpen] = useState(false)
106
108
  const [selectedData, setSelectedData] = useState()
@@ -130,8 +132,12 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
130
132
  }
131
133
  })
132
134
 
135
+ const unformatNumber = (formattedNumber: any) => {
136
+ return formattedNumber.replace(/\D/g, "")
137
+ }
138
+
133
139
  const showFormattedError = (reason = '') => {
134
- const countryName = itiInit.getSelectedCountryData().name
140
+ const countryName = itiRef.current.getSelectedCountryData().name
135
141
  const reasonText = reason.length > 0 ? ` (${reason})` : ''
136
142
  setError(`Invalid ${countryName} phone number${reasonText}`)
137
143
  return true
@@ -189,12 +195,12 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
189
195
  }
190
196
 
191
197
  const validateErrors = () => {
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
198
+ if (itiRef.current) isValid(itiRef.current.isValidNumber())
199
+ if (validateOnlyNumbers(itiRef.current)) return
200
+ if (validateTooLongNumber(itiRef.current)) return
201
+ if (validateTooShortNumber(itiRef.current)) return
202
+ if (validateUnhandledError(itiRef.current)) return
203
+ if (validateMissingAreaCode(itiRef.current)) return
198
204
  }
199
205
 
200
206
  const getCurrentSelectedData = (itiInit: any, inputValue: string) => {
@@ -203,10 +209,16 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
203
209
 
204
210
  const handleOnChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
205
211
  setInputValue(evt.target.value)
206
- const phoneNumberData = getCurrentSelectedData(itiInit, evt.target.value)
212
+ let phoneNumberData
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
+ }
207
219
  setSelectedData(phoneNumberData)
208
220
  onChange(phoneNumberData)
209
- isValid(itiInit.isValidNumber())
221
+ isValid(itiRef.current.isValidNumber())
210
222
  }
211
223
 
212
224
  // Separating Concerns as React Docs Recommend
@@ -230,9 +242,11 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
230
242
  onlyCountries,
231
243
  countrySearch: false,
232
244
  fixDropdownWidth: false,
233
- formatAsYouType: false,
245
+ formatAsYouType: formatAsYouType,
234
246
  })
235
247
 
248
+ itiRef.current = telInputInit;
249
+
236
250
  inputRef.current.addEventListener("countrychange", (evt: Event) => {
237
251
  const phoneNumberData = getCurrentSelectedData(telInputInit, (evt.target as HTMLInputElement).value)
238
252
  setSelectedData(phoneNumberData)
@@ -243,7 +257,11 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
243
257
  inputRef.current.addEventListener("open:countrydropdown", () => setDropDownIsOpen(true))
244
258
  inputRef.current.addEventListener("close:countrydropdown", () => setDropDownIsOpen(false))
245
259
 
246
- setItiInit(telInputInit)
260
+ if (formatAsYouType) {
261
+ inputRef.current?.addEventListener("input", (evt) => {
262
+ handleOnChange(evt as unknown as React.ChangeEvent<HTMLInputElement>);
263
+ });
264
+ }
247
265
  }, [])
248
266
 
249
267
  let textInputProps: {[key: string]: any} = {
@@ -0,0 +1,15 @@
1
+ <%= pb_rails("phone_number_input", props: {
2
+ id: "phone_number_input",
3
+ format_as_you_type: true
4
+ }) %>
5
+
6
+ <%= pb_rails("button", props: {id: "clickable", text: "Save Phone Number"}) %>
7
+
8
+ <%= javascript_tag do %>
9
+ document.querySelector('#clickable').addEventListener('click', () => {
10
+ const formattedPhoneNumber = document.querySelector('#phone_number_input').value
11
+ const unformattedPhoneNumber = formattedPhoneNumber.replace(/\D/g, "")
12
+
13
+ alert(`Formatted: ${formattedPhoneNumber}. Unformatted: ${unformattedPhoneNumber}`)
14
+ })
15
+ <% end %>
@@ -0,0 +1,24 @@
1
+ import React, { useState } from "react";
2
+ import { PhoneNumberInput, Body } from "playbook-ui";
3
+
4
+ const PhoneNumberInputFormat = (props) => {
5
+ const [phoneNumber, setPhoneNumber] = useState("");
6
+
7
+ const handleOnChange = ({ number }) => {
8
+ setPhoneNumber(number);
9
+ };
10
+
11
+ return (
12
+ <>
13
+ <PhoneNumberInput
14
+ formatAsYouType
15
+ id="format"
16
+ onChange={handleOnChange}
17
+ {...props}
18
+ />
19
+ {phoneNumber && <Body>Unformatted number: {phoneNumber}</Body>}
20
+ </>
21
+ );
22
+ };
23
+
24
+ export default PhoneNumberInputFormat;
@@ -0,0 +1 @@
1
+ NOTE: the `number` in the React `onChange` event will not include formatting (no spaces, dashes, and parentheses). For Rails, the `value` will include formatting and its value must be sanitized manually.
@@ -8,10 +8,12 @@ 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
11
12
 
12
13
  rails:
13
14
  - phone_number_input_default: Default
14
15
  - phone_number_input_preferred_countries: Preferred Countries
15
16
  - phone_number_input_initial_country: Initial Country
16
17
  - phone_number_input_only_countries: Limited Countries
17
- - phone_number_input_validation: Form Validation
18
+ - phone_number_input_validation: Form Validation
19
+ - phone_number_input_format: Format as You Type
@@ -5,3 +5,4 @@ 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,6 +21,8 @@ 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
24
26
 
25
27
  def classname
26
28
  generate_classname("pb_phone_number_input")
@@ -32,6 +34,7 @@ module Playbook
32
34
  dark: dark,
33
35
  disabled: disabled,
34
36
  error: error,
37
+ formatAsYouType: format_as_you_type,
35
38
  initialCountry: initial_country,
36
39
  label: label,
37
40
  name: name,
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { render, screen } from "../utilities/test-utils";
2
+ import { render, screen, act } from "../utilities/test-utils";
3
3
  import PhoneNumberInput from "./_phone_number_input";
4
4
 
5
5
  const testId = "phoneNumberInput";
@@ -120,3 +120,22 @@ 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,9 +4,23 @@
4
4
  data: object.data,
5
5
  id: object.id,
6
6
  **combined_html_options) do %>
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)) )%>
7
+ <% if enable_drag %>
8
+ <%= pb_rails("draggable", props: {initial_items: object.items}) do %>
9
+ <%= pb_rails("draggable/draggable_container") do %>
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 %>
10
24
  <% end %>
11
25
  <% end %>
12
26
  <% end %>
@@ -14,6 +14,9 @@ module Playbook
14
14
  prop :items, type: Playbook::Props::Array,
15
15
  default: []
16
16
 
17
+ prop :enable_drag, type: Playbook::Props::Boolean,
18
+ default: false
19
+
17
20
  def classname
18
21
  generate_classname("pb_selectable_list_kit")
19
22
  end
@@ -4,6 +4,13 @@
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 %>
7
14
  <% if object.variant == "radio"%>
8
15
  <%= pb_rails("radio", props: { text: object.text, checked: object.checked, input_options: object.input_options } ) %>
9
16
  <% if content.present? %>
@@ -19,10 +26,10 @@
19
26
  <% if object.variant == "checkbox"%>
20
27
  <script>
21
28
  var checkboxElement = document.querySelector("#<%=object.id%> input[type=checkbox]")
22
-
29
+
23
30
  checkboxElement.addEventListener("change", (evt) => {
24
31
  var listItemElement = document.querySelector("#<%=object.id%>")
25
-
32
+
26
33
  if (evt.target.checked) {
27
34
  listItemElement.classList.add("checked_item");
28
35
  } else {
@@ -34,9 +41,9 @@
34
41
  <script>
35
42
  var radioElement = document.querySelector("#<%=object.id%> input[type=radio]")
36
43
 
37
- radioElement.addEventListener("change", () => {
44
+ radioElement.addEventListener("change", () => {
38
45
  var radios = radioElement.closest("ul").querySelectorAll("input[type=radio]")
39
-
46
+
40
47
  radios.forEach((radio) => {
41
48
  if (radio.checked) {
42
49
  radio.closest("li").classList.add("checked_item");
@@ -6,6 +6,9 @@ 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
9
12
  prop :name, type: Playbook::Props::String
10
13
  prop :text, type: Playbook::Props::String
11
14
  prop :value, type: Playbook::Props::String
@@ -2,7 +2,6 @@ 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 '.'
6
5
  import {
7
6
  TableHead,
8
7
  TableHeader,
@@ -10,6 +9,7 @@ import {
10
9
  TableRow,
11
10
  TableCell,
12
11
  } from "./subcomponents";
12
+ import { addDataTitle } from './utilities/addDataTitle'
13
13
 
14
14
  type TableProps = {
15
15
  aria?: { [key: string]: string },
@@ -196,8 +196,7 @@ const Table = (props: TableProps): React.ReactElement => {
196
196
  }, [stickyRightColumn]);
197
197
 
198
198
  useEffect(() => {
199
- const instance = new PbTable()
200
- instance.connect()
199
+ addDataTitle()
201
200
  }, [])
202
201
 
203
202
  return (