playbook_ui 14.11.0 → 14.11.1.pre.alpha.PBNTR440enableglobalpropspbformwith5624

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.
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}