playbook_ui 14.11.0 → 14.11.1.pre.alpha.PBNTR440enableglobalpropspbformwith5624

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +18 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +27 -5
  5. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +17 -2
  6. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +23 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +29 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +61 -4
  9. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +1 -1
  10. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +2 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.jsx +50 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.jsx +1 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.jsx +1 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.jsx +60 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.md +5 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions.jsx +78 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions.md +1 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header.jsx +53 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header.md +1 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.jsx +52 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.md +1 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_control.md +2 -2
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props.html.erb +33 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_rails.md +1 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_no_subrows.json +42 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_with_id.json +299 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +6 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +6 -1
  29. data/app/pb_kits/playbook/pb_avatar_action_button/_avatar_action_button.scss +9 -11
  30. data/app/pb_kits/playbook/pb_badge/_badge.scss +2 -4
  31. data/app/pb_kits/playbook/pb_bread_crumbs/_bread_crumbs.scss +1 -3
  32. data/app/pb_kits/playbook/pb_button/_button.scss +1 -3
  33. data/app/pb_kits/playbook/pb_button/button.html.erb +2 -3
  34. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +1 -6
  35. data/app/pb_kits/playbook/pb_circle_icon_button/_circle_icon_button.scss +2 -4
  36. data/app/pb_kits/playbook/pb_collapsible/collapsible.html.erb +3 -1
  37. data/app/pb_kits/playbook/pb_collapsible/collapsible.rb +3 -0
  38. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +24 -16
  39. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +2 -0
  40. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_default_date.md +1 -1
  41. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_turbo_frames.html.erb +13 -0
  42. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_turbo_frames_rails.md +3 -0
  43. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +1 -0
  44. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_input_styles.scss +1 -3
  45. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_overrides.scss +3 -5
  46. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.scss +4 -6
  47. data/app/pb_kits/playbook/pb_date_time_stacked/_date_time_stacked.scss +2 -4
  48. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.html.erb +3 -9
  49. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.md +5 -0
  50. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.html.erb +38 -0
  51. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.md +3 -0
  52. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -0
  53. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +145 -183
  54. data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +158 -268
  55. data/app/pb_kits/playbook/pb_drawer/context.ts +11 -0
  56. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_behavior.jsx +38 -0
  57. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +3 -45
  58. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +0 -1
  59. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.jsx +9 -16
  60. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +44 -19
  61. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.md +21 -3
  62. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +16 -21
  63. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.jsx +2 -19
  64. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +2 -1
  65. data/app/pb_kits/playbook/pb_drawer/docs/index.js +1 -0
  66. data/app/pb_kits/playbook/pb_drawer/drawer.test.jsx +5 -5
  67. data/app/pb_kits/playbook/pb_drawer/hooks/useBreakpoint.tsx +60 -0
  68. data/app/pb_kits/playbook/pb_drawer/hooks/useDrawerAnimation.tsx +21 -0
  69. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +8 -10
  70. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.md +1 -1
  71. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +7 -12
  72. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +9 -14
  73. data/app/pb_kits/playbook/pb_dropdown/dropdown_option.html.erb +6 -11
  74. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +8 -14
  75. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +4 -6
  76. data/app/pb_kits/playbook/pb_icon_button/_icon_button.scss +78 -0
  77. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_default.html.erb +3 -0
  78. data/app/pb_kits/playbook/pb_icon_button/docs/example.yml +7 -0
  79. data/app/pb_kits/playbook/pb_icon_button/icon_button.html.erb +16 -0
  80. data/app/pb_kits/playbook/pb_icon_button/icon_button.rb +22 -0
  81. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.scss +1 -3
  82. data/app/pb_kits/playbook/pb_label_value/_label_value.scss +2 -4
  83. data/app/pb_kits/playbook/pb_list/item.html.erb +30 -8
  84. data/app/pb_kits/playbook/pb_list/item.rb +7 -0
  85. data/app/pb_kits/playbook/pb_list/list.html.erb +31 -11
  86. data/app/pb_kits/playbook/pb_list/list.rb +4 -0
  87. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.tsx +6 -1
  88. data/app/pb_kits/playbook/pb_message/_message_mixins.scss +1 -3
  89. data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.scss +5 -3
  90. data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.tsx +1 -0
  91. data/app/pb_kits/playbook/pb_multiple_users/multiple_users.html.erb +1 -1
  92. data/app/pb_kits/playbook/pb_passphrase/_passphrase.scss +3 -5
  93. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +8 -10
  94. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +30 -12
  95. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.html.erb +15 -0
  96. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.jsx +24 -0
  97. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.md +1 -0
  98. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +3 -1
  99. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  100. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  101. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +20 -1
  102. data/app/pb_kits/playbook/pb_pill/_pill.scss +2 -4
  103. data/app/pb_kits/playbook/pb_progress_simple/_progress_simple.scss +2 -4
  104. data/app/pb_kits/playbook/pb_radio/_radio.scss +12 -8
  105. data/app/pb_kits/playbook/pb_radio/docs/_radio_custom_children.jsx +8 -3
  106. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.scss +2 -4
  107. data/app/pb_kits/playbook/pb_select/_select.scss +6 -10
  108. data/app/pb_kits/playbook/pb_select/_select.tsx +5 -1
  109. data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
  110. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.scss +3 -5
  111. data/app/pb_kits/playbook/pb_selectable_icon/_selectable_icon.tsx +9 -1
  112. data/app/pb_kits/playbook/pb_selectable_icon/docs/_selectable_icon_default.jsx +4 -1
  113. data/app/pb_kits/playbook/pb_selectable_icon/docs/_selectable_icon_single_select.jsx +4 -1
  114. data/app/pb_kits/playbook/pb_selectable_list/selectable_list.html.erb +17 -3
  115. data/app/pb_kits/playbook/pb_selectable_list/selectable_list.rb +3 -0
  116. data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.html.erb +11 -4
  117. data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.rb +3 -0
  118. data/app/pb_kits/playbook/pb_table/_table.tsx +2 -3
  119. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns.html.erb +74 -0
  120. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns_rails.md +3 -0
  121. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_rails.md +2 -2
  122. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns.html.erb +74 -0
  123. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns_rails.md +3 -0
  124. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible.html.erb +47 -0
  125. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_rails.md +2 -0
  126. data/app/pb_kits/playbook/pb_table/docs/example.yml +3 -0
  127. data/app/pb_kits/playbook/pb_table/index.ts +187 -88
  128. data/app/pb_kits/playbook/pb_table/styles/_collapsible.scss +12 -0
  129. data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +6 -5
  130. data/app/pb_kits/playbook/pb_table/table.html.erb +1 -1
  131. data/app/pb_kits/playbook/pb_table/table.rb +17 -2
  132. data/app/pb_kits/playbook/pb_table/table_row.html.erb +20 -1
  133. data/app/pb_kits/playbook/pb_table/table_row.rb +5 -0
  134. data/app/pb_kits/playbook/pb_table/utilities/addDataTitle.ts +22 -0
  135. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +1 -3
  136. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.html.erb +46 -0
  137. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask_rails.md +3 -0
  138. data/app/pb_kits/playbook/pb_text_input/docs/example.yml +2 -1
  139. data/app/pb_kits/playbook/pb_text_input/index.js +103 -0
  140. data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +4 -0
  141. data/app/pb_kits/playbook/pb_text_input/text_input.rb +33 -3
  142. data/app/pb_kits/playbook/pb_textarea/_textarea.scss +1 -3
  143. data/app/pb_kits/playbook/pb_time_range_inline/_time_range_inline.scss +4 -5
  144. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +32 -34
  145. data/app/pb_kits/playbook/pb_toggle/_toggle.scss +3 -5
  146. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +3 -2
  147. data/app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.tsx +12 -4
  148. data/app/pb_kits/playbook/pb_typeahead/components/Control.tsx +5 -1
  149. data/app/pb_kits/playbook/pb_typeahead/components/IndicatorsContainer.tsx +8 -3
  150. data/app/pb_kits/playbook/pb_typeahead/components/MenuList.tsx +6 -1
  151. data/app/pb_kits/playbook/pb_typeahead/components/Option.tsx +21 -6
  152. data/app/pb_kits/playbook/pb_typeahead/components/Placeholder.tsx +13 -6
  153. data/app/pb_kits/playbook/pb_typeahead/components/ValueContainer.tsx +7 -3
  154. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_custom_menu_list.jsx +2 -0
  155. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.html.erb +19 -0
  156. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.jsx +27 -0
  157. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.md +1 -0
  158. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills_async.jsx +4 -2
  159. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_pills_async_custom_options.jsx +5 -5
  160. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
  161. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  162. data/dist/chunks/_typeahead-BWwaAo_0.js +36 -0
  163. data/dist/chunks/_weekday_stacked-zyBCd1s8.js +45 -0
  164. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  165. data/dist/chunks/{lib-B7sgJtGS.js → lib-kMuhBuU7.js} +2 -2
  166. data/dist/chunks/{pb_form_validation-C5Cc0-1v.js → pb_form_validation-DBJ0wZuS.js} +1 -1
  167. data/dist/chunks/vendor.js +1 -1
  168. data/dist/menu.yml +6 -0
  169. data/dist/playbook-doc.js +1 -1
  170. data/dist/playbook-rails-react-bindings.js +1 -1
  171. data/dist/playbook-rails.js +1 -1
  172. data/dist/playbook.css +1 -1
  173. data/lib/playbook/pb_forms_global_props_helper.rb +136 -0
  174. data/lib/playbook/pb_forms_helper.rb +13 -4
  175. data/lib/playbook/version.rb +2 -2
  176. metadata +67 -9
  177. data/dist/chunks/_typeahead-C2iCBqxQ.js +0 -36
  178. data/dist/chunks/_weekday_stacked-E-5KcEkc.js +0 -45
  179. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
  180. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_table_props.md → _advanced_table_table_props_react.md} +0 -0
  181. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible.md → _table_with_collapsible_react.md} +0 -0
@@ -0,0 +1,46 @@
1
+ <%= pb_rails("text_input", props: {
2
+ label: "Currency",
3
+ mask: "currency",
4
+ margin_bottom: "md",
5
+ name: "currency_name",
6
+ placeholder:"$0.00"
7
+ }) %>
8
+
9
+ <%= pb_rails("text_input", props: {
10
+ label: "ZIP Code",
11
+ mask: "zip_code",
12
+ margin_bottom: "md",
13
+ placeholder: "12345"
14
+ }) %>
15
+
16
+ <%= pb_rails("text_input", props: {
17
+ label: "Postal Code",
18
+ mask: "postal_code",
19
+ placeholder: "12345-6789",
20
+ margin_bottom: "md",
21
+ }) %>
22
+
23
+ <%= pb_rails("text_input", props: {
24
+ label: "SSN",
25
+ mask: "ssn",
26
+ margin_bottom: "md",
27
+ placeholder: "123-45-6789"
28
+ }) %>
29
+
30
+ <%= pb_rails("title" , props: {
31
+ text: "Hidden Input Under The Hood",
32
+ padding_bottom: "sm"
33
+ })%>
34
+
35
+ <%= pb_rails("text_input", props: {
36
+ label: "Currency",
37
+ mask: "currency",
38
+ margin_bottom: "md",
39
+ name: "currency_name",
40
+ id: "example-currency",
41
+ placeholder: "$0.00",
42
+ }) %>
43
+
44
+ <style>
45
+ #example-currency-sanitized {display: flex !important;}
46
+ </style>
@@ -0,0 +1,3 @@
1
+ The mask prop lets you style your inputs while maintaining the value that the user typed in.
2
+
3
+ It uses a hidden input field to submit the unformatted value as it will have the proper `name` attribute. It will also copy the id field with a `"#{your-id-sanitized}"`
@@ -8,6 +8,7 @@ examples:
8
8
  - text_input_inline: Inline
9
9
  - text_input_no_label: No Label
10
10
  - text_input_options: Input Options
11
+ - text_input_mask: Mask
11
12
  react:
12
13
  - text_input_default: Default
13
14
  - text_input_error: With Error
@@ -23,4 +24,4 @@ examples:
23
24
  - text_input_error_swift: With Error
24
25
  - text_input_disabled_swift: Disabled
25
26
  - text_input_add_on_swift: Add On
26
- - text_input_props_swift: ""
27
+ - text_input_props_swift: ""
@@ -0,0 +1,103 @@
1
+ export default class PbTextInput {
2
+ static start() {
3
+ const inputElements = document.querySelectorAll('[data-pb-input-mask="true"]');
4
+
5
+ inputElements.forEach((inputElement) => {
6
+ inputElement.addEventListener("input", (event) => {
7
+ const maskType = inputElement.getAttribute("mask");
8
+ const cursorPosition = inputElement.selectionStart;
9
+
10
+ let rawValue = event.target.value;
11
+ let formattedValue = rawValue;
12
+
13
+ // Apply formatting based on the mask type
14
+ switch (maskType) {
15
+ case "currency":
16
+ formattedValue = formatCurrency(rawValue);
17
+ break;
18
+ case "ssn":
19
+ formattedValue = formatSSN(rawValue);
20
+ break;
21
+ case "postal_code":
22
+ formattedValue = formatPostalCode(rawValue);
23
+ break;
24
+ case "zip_code":
25
+ formattedValue = formatZipCode(rawValue);
26
+ break;
27
+ }
28
+
29
+ // Update the sanitized input field in the same wrapper
30
+ const sanitizedInput = inputElement
31
+ .closest(".text_input_wrapper")
32
+ ?.querySelector('[data="sanitized-pb-input"]');
33
+
34
+ if (sanitizedInput) {
35
+ switch (maskType) {
36
+ case "ssn":
37
+ sanitizedInput.value = sanitizeSSN(formattedValue);
38
+ break;
39
+ case "currency":
40
+ sanitizedInput.value = sanitizeCurrency(formattedValue);
41
+ break;
42
+ default:
43
+ sanitizedInput.value = formattedValue;
44
+ }
45
+ }
46
+
47
+ inputElement.value = formattedValue;
48
+ setCursorPosition(inputElement, cursorPosition, rawValue, formattedValue);
49
+ });
50
+ });
51
+
52
+ }
53
+ }
54
+
55
+ function formatCurrency(value) {
56
+ const numericValue = value.replace(/[^0-9]/g, "").slice(0, 15);
57
+
58
+ if (!numericValue) return "";
59
+
60
+ const dollars = parseFloat((parseInt(numericValue) / 100).toFixed(2));
61
+ if (dollars === 0) return "";
62
+
63
+ return new Intl.NumberFormat("en-US", {
64
+ style: "currency",
65
+ currency: "USD",
66
+ maximumFractionDigits: 2,
67
+ }).format(dollars);
68
+ }
69
+
70
+ function formatSSN(value) {
71
+ const cleaned = value.replace(/\D/g, "").slice(0, 9);
72
+ return cleaned
73
+ .replace(/(\d{5})(?=\d)/, "$1-")
74
+ .replace(/(\d{3})(?=\d)/, "$1-");
75
+ }
76
+
77
+ function formatZipCode(value) {
78
+ return value.replace(/\D/g, "").slice(0, 5);
79
+ }
80
+
81
+ function formatPostalCode(value) {
82
+ const cleaned = value.replace(/\D/g, "").slice(0, 9);
83
+ return cleaned.replace(/(\d{5})(?=\d)/, "$1-");
84
+ }
85
+
86
+ function sanitizeSSN(input) {
87
+ return input.replace(/\D/g, "");
88
+ }
89
+
90
+ function sanitizeCurrency(input) {
91
+ return input.replace(/[$,]/g, "");
92
+ }
93
+
94
+ // function to set cursor position
95
+ function setCursorPosition(inputElement, cursorPosition, rawValue, formattedValue) {
96
+ const difference = formattedValue.length - rawValue.length;
97
+
98
+ const newPosition = Math.max(0, cursorPosition + difference);
99
+
100
+ requestAnimationFrame(() => {
101
+ inputElement.setSelectionRange(newPosition, newPosition);
102
+ });
103
+ }
@@ -13,9 +13,13 @@
13
13
  <%= pb_rails("text_input/add_on", props: object.add_on_props) do %>
14
14
  <%= input_tag %>
15
15
  <% end %>
16
+ <% elsif mask.present? %>
17
+ <%= input_tag %>
18
+ <%= tag(:input, data: "sanitized-pb-input", id: sanitized_id, name: object.name, style: "display: none;") %>
16
19
  <% else %>
17
20
  <%= input_tag %>
18
21
  <% end %>
19
22
  <%= pb_rails("body", props: {dark: object.dark, status: "negative", text: object.error}) if object.error %>
20
23
  <% end %>
21
24
  <% end %>
25
+
@@ -4,6 +4,15 @@
4
4
  module Playbook
5
5
  module PbTextInput
6
6
  class TextInput < Playbook::KitBase
7
+ VALID_MASKS = %w[currency zipCode postalCode ssn].freeze
8
+
9
+ MASK_PATTERNS = {
10
+ "currency" => '^\$\d{1,3}(?:,\d{3})*(?:\.\d{2})?$',
11
+ "zip_code" => '\d{5}',
12
+ "postal_code" => '\d{5}-\d{4}',
13
+ "ssn" => '\d{3}-\d{2}-\d{4}',
14
+ }.freeze
15
+
7
16
  prop :autocomplete, type: Playbook::Props::Boolean,
8
17
  default: true
9
18
  prop :disabled, type: Playbook::Props::Boolean,
@@ -25,6 +34,9 @@ module Playbook
25
34
  prop :add_on, type: Playbook::Props::NestedProps,
26
35
  nested_kit: Playbook::PbTextInput::AddOn
27
36
 
37
+ prop :mask, type: Playbook::Props::String,
38
+ default: nil
39
+
28
40
  def classname
29
41
  default_margin_bottom = margin_bottom.present? ? "" : " mb_sm"
30
42
  generate_classname("pb_text_input_kit") + default_margin_bottom + error_class + inline_class
@@ -46,6 +58,10 @@ module Playbook
46
58
  { dark: dark }.merge(add_on || {})
47
59
  end
48
60
 
61
+ def sanitized_id
62
+ "#{object.id}-sanitized" if id.present?
63
+ end
64
+
49
65
  private
50
66
 
51
67
  def all_input_options
@@ -55,12 +71,13 @@ module Playbook
55
71
  data: validation_data,
56
72
  disabled: disabled,
57
73
  id: input_options.dig(:id) || id,
58
- name: name,
59
- pattern: validation_pattern,
74
+ name: mask.present? ? "" : name,
75
+ pattern: validation_pattern || mask_pattern,
60
76
  placeholder: placeholder,
61
77
  required: required,
62
78
  type: type,
63
79
  value: value,
80
+ mask: mask,
64
81
  }.merge(input_options)
65
82
  end
66
83
 
@@ -75,7 +92,7 @@ module Playbook
75
92
  def validation_data
76
93
  fields = input_options.dig(:data) || {}
77
94
  fields[:message] = validation_message unless validation_message.blank?
78
- fields
95
+ mask ? fields.merge(pb_input_mask: true) : fields
79
96
  end
80
97
 
81
98
  def error_class
@@ -85,6 +102,19 @@ module Playbook
85
102
  def inline_class
86
103
  inline ? " inline" : ""
87
104
  end
105
+
106
+ def mask_data
107
+ return {} unless mask
108
+ raise ArgumentError, "mask must be one of: #{VALID_MASKS.join(', ')}" unless VALID_MASKS.include?(mask)
109
+
110
+ { mask: mask }
111
+ end
112
+
113
+ def mask_pattern
114
+ return nil unless mask
115
+
116
+ MASK_PATTERNS[mask]
117
+ end
88
118
  end
89
119
  end
90
120
  end
@@ -1,5 +1,3 @@
1
- @use "sass:math";
2
-
3
1
  @import "../pb_body/body_mixins";
4
2
  @import "./textarea_mixin";
5
3
  @import "../tokens/spacing";
@@ -62,7 +60,7 @@
62
60
 
63
61
  &.error {
64
62
  [class*=pb_body_kit] {
65
- margin-top: math.div($space_xs, 2);
63
+ margin-top: $space_xs / 2;
66
64
  }
67
65
  textarea {
68
66
  border-color: $error;
@@ -1,4 +1,3 @@
1
- @use "sass:math";
2
1
 
3
2
  [class^=pb_time_range_inline_kit] {
4
3
  &[class*=_center] {
@@ -23,14 +22,14 @@
23
22
  display: flex;
24
23
  align-items: center;
25
24
  [class*=pb_time_range_inline_arrow] {
26
- margin-left: math.div($space_xs, 2);
27
- margin-right:math.div($space_xs, 2);
25
+ margin-left: $space_xs/2;
26
+ margin-right: $space_xs/2;
28
27
  }
29
28
  [class*=pb_time_range_inline_timezone] {
30
- margin-left: math.div($space_xs, 2);
29
+ margin-left: $space_xs/2;
31
30
  }
32
31
  [class*=pb_time_range_inline_icon] {
33
- margin-right: math.div($space_xs, 2);
32
+ margin-right: $space_xs/2;
34
33
  }
35
34
  }
36
35
  }
@@ -1,14 +1,12 @@
1
- @use "sass:math";
2
-
3
1
  @import "../tokens/colors";
4
2
  @import "../tokens/spacing";
5
3
  @import "../tokens/opacity";
6
4
  @import "../tokens/typography";
7
5
 
8
6
  $connector_width: 2px;
9
- $icon_margin: math.div($space_xs, 2);
7
+ $icon_margin: $space_xs/2;
10
8
  $icon_height: 28px;
11
- $height_from_top: (math.div($icon_height, 2)) - (math.div($connector_width, 2));
9
+ $height_from_top: $icon_height/2 - $connector_width/2;
12
10
 
13
11
  // Add gap variables
14
12
  $gap_xs: $height_from_top + $space_xs;
@@ -52,7 +50,7 @@ $gap_lg: $height_from_top + $space_lg;
52
50
  >div {
53
51
  &:last-child {
54
52
  flex-basis: auto !important;
55
- [class=pb_timeline_item_step] {
53
+ [class^=pb_timeline_item_step] {
56
54
  [class=pb_timeline_item_connector] {
57
55
  opacity: 0;
58
56
  }
@@ -68,29 +66,25 @@ $gap_lg: $height_from_top + $space_lg;
68
66
  [class*=pb_timeline_item_kit] {
69
67
  &[class*=_solid] {
70
68
  flex-basis: 100%;
71
- [class=pb_timeline_item_left_block] {
72
- height: 0px;
73
- }
74
- [class=pb_timeline_item_step] {
69
+ [class^=pb_timeline_item_step] {
75
70
  @include flex_wrapper(row);
71
+ align-items: center;
76
72
  margin-top: $space_xs;
77
73
  margin-bottom: $space_xs;
78
74
  [class=pb_timeline_item_connector] {
79
- @include pb_timeline_line_solid($connector_width, $connector_width, $height_from_top $icon_margin 0 $icon_margin );
75
+ @include pb_timeline_line_solid($connector_width, $connector_width, 0 $icon_margin 0 $icon_margin );
80
76
  }
81
77
  }
82
78
  }
83
79
  &[class*=_dotted] {
84
80
  flex-basis: 100%;
85
- [class=pb_timeline_item_left_block] {
86
- height: 0;
87
- }
88
- [class=pb_timeline_item_step] {
81
+ [class^=pb_timeline_item_step] {
89
82
  @include flex_wrapper(row);
83
+ align-items: center;
90
84
  margin-top: $space_xs;
91
85
  margin-bottom: $space_xs;
92
86
  [class=pb_timeline_item_connector] {
93
- @include pb_timeline_line_dotted_horizontal($connector_width, $connector_width, $height_from_top $icon_margin 0 $icon_margin );
87
+ @include pb_timeline_line_dotted_horizontal($connector_width, $connector_width, 0 $icon_margin 0 $icon_margin );
94
88
  }
95
89
  }
96
90
  }
@@ -101,7 +95,7 @@ $gap_lg: $height_from_top + $space_lg;
101
95
  >div {
102
96
  &:last-child {
103
97
  flex-basis: auto !important;
104
- [class=pb_timeline_item_step] {
98
+ [class^=pb_timeline_item_step] {
105
99
  [class=pb_timeline_item_connector] {
106
100
  opacity: 0;
107
101
  }
@@ -131,12 +125,12 @@ $gap_lg: $height_from_top + $space_lg;
131
125
  }
132
126
  }
133
127
  }
134
- [class=pb_timeline_item_step] {
128
+ [class^=pb_timeline_item_step] {
135
129
  @include flex_wrapper(row);
136
130
  margin-top: $space_xs;
137
131
  margin-bottom: $space_xs;
138
132
  [class=pb_timeline_item_connector] {
139
- @include pb_timeline_line_solid($connector_width, $connector_width, $height_from_top $icon_margin 0 $icon_margin );
133
+ @include pb_timeline_line_solid($connector_width, $connector_width, 0 $icon_margin 0 $icon_margin );
140
134
  }
141
135
  }
142
136
  }
@@ -155,12 +149,12 @@ $gap_lg: $height_from_top + $space_lg;
155
149
  }
156
150
  }
157
151
  }
158
- [class=pb_timeline_item_step] {
152
+ [class^=pb_timeline_item_step] {
159
153
  @include flex_wrapper(row);
160
154
  margin-top: $space_xs;
161
155
  margin-bottom: $space_xs;
162
156
  [class=pb_timeline_item_connector] {
163
- @include pb_timeline_line_dotted_horizontal($connector_width, $connector_width, $height_from_top $icon_margin 0 $icon_margin );
157
+ @include pb_timeline_line_dotted_horizontal($connector_width, $connector_width, 0 $icon_margin 0 $icon_margin );
164
158
  }
165
159
  }
166
160
  }
@@ -172,7 +166,7 @@ $gap_lg: $height_from_top + $space_lg;
172
166
  align-items: flex-start;
173
167
  align-self: auto;
174
168
  >div:last-child {
175
- [class=pb_timeline_item_step] {
169
+ [class^=pb_timeline_item_step] {
176
170
  [class=pb_timeline_item_connector] {
177
171
  opacity: 0;
178
172
  }
@@ -182,13 +176,14 @@ $gap_lg: $height_from_top + $space_lg;
182
176
  @include flex_wrapper(row);
183
177
  &[class*=_solid] {
184
178
  flex-basis: 100%;
185
- [class=pb_timeline_item_step] {
179
+ [class^=pb_timeline_item_step] {
186
180
  @include flex_wrapper(column);
181
+ align-items: center;
187
182
  align-content: flex-start;
188
183
  margin-right: $space_sm;
189
184
  margin-left: $space_sm;
190
185
  [class=pb_timeline_item_connector] {
191
- @include pb_timeline_line_solid($connector_width, $connector_width, $icon_margin 0 $icon_margin $height_from_top);
186
+ @include pb_timeline_line_solid($connector_width, $connector_width, $icon_margin 0 $icon_margin 0);
192
187
  }
193
188
  }
194
189
  [class=pb_timeline_item_left_block] {
@@ -202,12 +197,13 @@ $gap_lg: $height_from_top + $space_lg;
202
197
  }
203
198
  &[class*=_dotted] {
204
199
  flex-basis: 100%;
205
- [class=pb_timeline_item_step] {
200
+ [class^=pb_timeline_item_step] {
206
201
  @include flex_wrapper(column);
202
+ align-items: center;
207
203
  margin-right: $space_sm;
208
204
  margin-left: $space_sm;
209
205
  [class=pb_timeline_item_connector] {
210
- @include pb_timeline_line_dotted_vertical($connector_width, $connector_width, $icon_margin 0 $icon_margin $height_from_top);
206
+ @include pb_timeline_line_dotted_vertical($connector_width, $connector_width, $icon_margin 0 $icon_margin 0);
211
207
  }
212
208
  }
213
209
  [class=pb_timeline_item_left_block] {
@@ -225,7 +221,7 @@ $gap_lg: $height_from_top + $space_lg;
225
221
  align-items: flex-start;
226
222
  align-self: auto;
227
223
  >div:last-child {
228
- [class=pb_timeline_item_step] {
224
+ [class^=pb_timeline_item_step] {
229
225
  [class=pb_timeline_item_connector] {
230
226
  opacity: 0;
231
227
  }
@@ -235,13 +231,14 @@ $gap_lg: $height_from_top + $space_lg;
235
231
  @include flex_wrapper(row);
236
232
  &[class*=_solid] {
237
233
  flex-basis: 100%;
238
- [class=pb_timeline_item_step] {
234
+ [class^=pb_timeline_item_step] {
239
235
  @include flex_wrapper(column);
236
+ align-items: center;
240
237
  align-content: flex-start;
241
238
  margin-right: $space_sm;
242
239
  margin-left: $space_sm;
243
240
  [class=pb_timeline_item_connector] {
244
- @include pb_timeline_line_solid($connector_width, $connector_width, $icon_margin 0 $icon_margin $height_from_top);
241
+ @include pb_timeline_line_solid($connector_width, $connector_width, $icon_margin 0 $icon_margin 0);
245
242
  }
246
243
  }
247
244
  [class=pb_timeline_item_left_block] {
@@ -255,12 +252,13 @@ $gap_lg: $height_from_top + $space_lg;
255
252
  }
256
253
  &[class*=_dotted] {
257
254
  flex-basis: 100%;
258
- [class=pb_timeline_item_step] {
255
+ [class^=pb_timeline_item_step] {
259
256
  @include flex_wrapper(column);
257
+ align-items: center;
260
258
  margin-right: $space_sm;
261
259
  margin-left: $space_sm;
262
260
  [class=pb_timeline_item_connector] {
263
- @include pb_timeline_line_dotted_vertical($connector_width, $connector_width, $icon_margin 0 $icon_margin $height_from_top);
261
+ @include pb_timeline_line_dotted_vertical($connector_width, $connector_width, $icon_margin 0 $icon_margin 0);
264
262
  }
265
263
  }
266
264
  [class=pb_timeline_item_left_block] {
@@ -276,7 +274,7 @@ $gap_lg: $height_from_top + $space_lg;
276
274
  }
277
275
  &[class*=_gap_xs] {
278
276
  [class*=pb_timeline_item_kit] {
279
- [class=pb_timeline_item_step] {
277
+ [class^=pb_timeline_item_step] {
280
278
  [class=pb_timeline_item_connector] {
281
279
  height: $gap_xs !important;
282
280
  }
@@ -285,7 +283,7 @@ $gap_lg: $height_from_top + $space_lg;
285
283
  }
286
284
  &[class*=_gap_sm] {
287
285
  [class*=pb_timeline_item_kit] {
288
- [class=pb_timeline_item_step] {
286
+ [class^=pb_timeline_item_step] {
289
287
  [class=pb_timeline_item_connector] {
290
288
  height: $gap_sm !important;
291
289
  }
@@ -294,7 +292,7 @@ $gap_lg: $height_from_top + $space_lg;
294
292
  }
295
293
  &[class*=_gap_md] {
296
294
  [class*=pb_timeline_item_kit] {
297
- [class=pb_timeline_item_step] {
295
+ [class^=pb_timeline_item_step] {
298
296
  [class=pb_timeline_item_connector] {
299
297
  height: $gap_md !important;
300
298
  }
@@ -303,7 +301,7 @@ $gap_lg: $height_from_top + $space_lg;
303
301
  }
304
302
  &[class*=_gap_lg] {
305
303
  [class*=pb_timeline_item_kit] {
306
- [class=pb_timeline_item_step] {
304
+ [class^=pb_timeline_item_step] {
307
305
  [class=pb_timeline_item_connector] {
308
306
  height: $gap_lg !important;
309
307
  }
@@ -1,5 +1,3 @@
1
- @use "sass:math";
2
-
3
1
  @import "../tokens/colors";
4
2
 
5
3
  $color_checkbox_success: $data_1;
@@ -10,7 +8,7 @@ $transition: .2s ease-in-out;
10
8
  [class^=pb_toggle_kit] {
11
9
  position: relative;
12
10
  $width: 44px;
13
- $height: math.div($width, 2);
11
+ $height: $width / 2;
14
12
  $border_success: 3px solid $color_checkbox_success;
15
13
  $border_default: 3px solid $color_checkbox_default;
16
14
 
@@ -29,7 +27,7 @@ $transition: .2s ease-in-out;
29
27
  &:after {
30
28
  transition: $transition;
31
29
  content: "";
32
- width: math.div($width, 2) - 4px;
30
+ width: $width / 2 - 4px;
33
31
  height: $height - 4px;
34
32
  background-color: $color_checkbox_default;
35
33
  border-radius: 50%;
@@ -70,7 +68,7 @@ $transition: .2s ease-in-out;
70
68
  background-color: $color_checkbox_success;
71
69
 
72
70
  &:after {
73
- left: math.div($width, 2) + 2px;
71
+ left: $width / 2 + 2px;
74
72
  background-color: $white;
75
73
  }
76
74
  }
@@ -42,8 +42,8 @@ type TypeaheadProps = {
42
42
  id?: string,
43
43
  label?: string,
44
44
  loadOptions?: string | Noop,
45
- getOptionLabel?: string | (() => any),
46
- getOptionValue?: string | (() => any),
45
+ getOptionLabel?: string | (() => string),
46
+ getOptionValue?: string | (() => string),
47
47
  name?: string,
48
48
  marginBottom?: "none" | "xxs" | "xs" | "sm" | "md" | "lg" | "xl",
49
49
  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",
@@ -109,6 +109,7 @@ const Typeahead = ({
109
109
  multiKit: '',
110
110
  onCreateOption: null as null,
111
111
  plusIcon: false,
112
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
112
113
  onMultiValueClick: (_option: SelectValueType): any => undefined,
113
114
  pillColor: pillColor,
114
115
  ...props,
@@ -1,16 +1,24 @@
1
1
  import React, { useEffect } from 'react'
2
2
  import { components } from 'react-select'
3
3
 
4
- const ClearContainer = (props: any) => {
4
+ type ClearContainerProps = {
5
+ children: React.ReactNode,
6
+ selectProps?: {
7
+ id: string,
8
+ },
9
+ clearValue: () => void,
10
+ }
11
+
12
+ const ClearContainer = (props: ClearContainerProps): React.ReactElement => {
5
13
  const { selectProps, clearValue } = props
6
14
  useEffect(() => {
7
15
  document.addEventListener(`pb-typeahead-kit-${selectProps.id}:clear`, clearValue)
8
- }, [true])
16
+ }, [clearValue, selectProps.id])
9
17
 
10
18
  return (
11
19
  <components.ClearIndicator
12
- className="clear_indicator"
13
- {...props}
20
+ className="clear_indicator"
21
+ {...props}
14
22
  />
15
23
  )
16
24
  }
@@ -5,7 +5,11 @@ import Flex from '../../pb_flex/_flex'
5
5
  import TextInput from '../../pb_text_input/_text_input'
6
6
 
7
7
  type Props = {
8
- selectProps: any,
8
+ selectProps: {
9
+ dark?: boolean,
10
+ label: string,
11
+ error?: string,
12
+ },
9
13
  }
10
14
 
11
15
  const TypeaheadControl = (props: Props) => (
@@ -1,10 +1,15 @@
1
1
  import React from 'react'
2
2
  import { components } from 'react-select'
3
3
 
4
- const IndicatorsContainer = (props: any) => (
4
+ type IndicatorsContainerProps = {
5
+ children: React.ReactNode,
6
+ }
7
+
8
+
9
+ const IndicatorsContainer = (props: IndicatorsContainerProps): React.ReactElement => (
5
10
  <components.IndicatorsContainer
6
- className="text_input_indicators"
7
- {...props}
11
+ className="text_input_indicators"
12
+ {...props}
8
13
  />
9
14
  )
10
15
 
@@ -1,7 +1,12 @@
1
1
  import React from 'react'
2
2
  import { components } from 'react-select'
3
3
 
4
- const MenuList = (props: any) => {
4
+ type MenuListProps = {
5
+ children: React.ReactNode,
6
+ footer: React.ReactNode,
7
+ }
8
+
9
+ const MenuList = (props: MenuListProps): React.ReactElement => {
5
10
  return (
6
11
  <components.MenuList {...props}>
7
12
  {props.children}