playbook_ui 14.17.0.pre.rc.1 → 14.18.0.pre.alpha.PLAY20787400

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 (220) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +23 -3
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +67 -3
  4. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/Utilities/ExpansionControlHelpers.tsx +29 -19
  6. data/app/pb_kits/playbook/pb_advanced_table/Utilities/types.ts +1 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +133 -124
  8. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +92 -2
  9. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +20 -7
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_expand_by_depth.jsx +66 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_expand_by_depth.md +10 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.jsx +90 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.md +3 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_columns.jsx +58 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_columns.md +6 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_columns_and_header.jsx +64 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_columns_and_header.md +8 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.jsx +55 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.md +3 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.html.erb +33 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.md +3 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props.html.erb +1 -1
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props.jsx +1 -2
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_rails.md +2 -2
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_react.md +1 -1
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +6 -2
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +6 -2
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +9 -3
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +6 -1
  30. data/app/pb_kits/playbook/pb_advanced_table/index.js +7 -0
  31. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +97 -0
  32. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +1 -1
  33. data/app/pb_kits/playbook/pb_background/_background.scss +26 -0
  34. data/app/pb_kits/playbook/pb_background/_background.tsx +5 -3
  35. data/app/pb_kits/playbook/pb_background/background.test.js +5 -0
  36. data/app/pb_kits/playbook/pb_background/docs/_background_overlay.jsx +35 -0
  37. data/app/pb_kits/playbook/pb_background/docs/_background_overlay.md +1 -0
  38. data/app/pb_kits/playbook/pb_background/docs/example.yml +1 -0
  39. data/app/pb_kits/playbook/pb_background/docs/index.js +1 -0
  40. data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +1 -1
  41. data/app/pb_kits/playbook/pb_circle_chart/circleChart.test.js +2 -2
  42. data/app/pb_kits/playbook/pb_circle_chart/circleChartTheme.ts +53 -0
  43. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_block.html.erb +2 -2
  44. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_block.jsx +1 -1
  45. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_colors.html.erb +1 -1
  46. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_colors.jsx +1 -1
  47. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_custom_tooltip.html.erb +1 -1
  48. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_custom_tooltip.jsx +1 -1
  49. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_default.html.erb +1 -1
  50. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_default.jsx +1 -1
  51. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_legend_position.html.erb +1 -1
  52. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_legend_position.jsx +1 -1
  53. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_live_data.jsx +2 -2
  54. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_pb_styles.jsx +38 -0
  55. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_pb_styles.md +1 -0
  56. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_rounded.html.erb +1 -1
  57. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_rounded.jsx +1 -1
  58. data/app/pb_kits/playbook/pb_circle_chart/docs/example.yml +2 -3
  59. data/app/pb_kits/playbook/pb_circle_chart/docs/index.js +2 -1
  60. data/app/pb_kits/playbook/pb_circle_icon_button/_circle_icon_button.scss +39 -1
  61. data/app/pb_kits/playbook/pb_circle_icon_button/_circle_icon_button.tsx +4 -0
  62. data/app/pb_kits/playbook/pb_circle_icon_button/circle_icon_button.rb +9 -1
  63. data/app/pb_kits/playbook/pb_circle_icon_button/circle_icon_button.test.js +14 -0
  64. data/app/pb_kits/playbook/pb_circle_icon_button/docs/_circle_icon_button_size.html.erb +28 -0
  65. data/app/pb_kits/playbook/pb_circle_icon_button/docs/_circle_icon_button_size.jsx +42 -0
  66. data/app/pb_kits/playbook/pb_circle_icon_button/docs/_circle_icon_button_size.md +1 -0
  67. data/app/pb_kits/playbook/pb_circle_icon_button/docs/example.yml +2 -0
  68. data/app/pb_kits/playbook/pb_circle_icon_button/docs/index.js +1 -0
  69. data/app/pb_kits/playbook/pb_collapsible/__snapshots__/collapsible.test.js.snap +14 -7
  70. data/app/pb_kits/playbook/pb_contact/contact.test.js +7 -7
  71. data/app/pb_kits/playbook/pb_copy_button/_copy_button.tsx +19 -45
  72. data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_hook.jsx +54 -0
  73. data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_hook.md +3 -0
  74. data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_hook_rails.html.erb +14 -0
  75. data/app/pb_kits/playbook/pb_copy_button/docs/_copy_button_hook_rails.md +3 -0
  76. data/app/pb_kits/playbook/pb_copy_button/docs/example.yml +2 -0
  77. data/app/pb_kits/playbook/pb_copy_button/docs/index.js +2 -1
  78. data/app/pb_kits/playbook/pb_copy_button/index.js +46 -20
  79. data/app/pb_kits/playbook/pb_copy_button/usePBCopy.ts +45 -0
  80. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +12 -0
  81. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +12 -0
  82. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +50 -1
  83. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_rails.md +4 -0
  84. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_range_limit.md +1 -1
  85. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_react.md +5 -1
  86. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.jsx +34 -0
  87. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.md +14 -0
  88. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.html.erb +20 -0
  89. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.md +14 -0
  90. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
  91. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +1 -0
  92. data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +10 -0
  93. data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.test.js +2 -2
  94. data/app/pb_kits/playbook/pb_date_range_stacked/date_range_stacked.test.js +1 -1
  95. data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +10 -1
  96. data/app/pb_kits/playbook/pb_dialog/dialog.rb +2 -0
  97. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_turbo_frames.html.erb +117 -0
  98. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_turbo_frames_rails.md +9 -0
  99. data/app/pb_kits/playbook/pb_dialog/docs/example.yml +1 -0
  100. data/app/pb_kits/playbook/pb_dialog/index.js +106 -14
  101. data/app/pb_kits/playbook/pb_draggable/_draggable.scss +43 -20
  102. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +58 -17
  103. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.jsx +102 -105
  104. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.md +3 -3
  105. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.jsx +50 -48
  106. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.md +1 -1
  107. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line.jsx +110 -0
  108. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line.md +5 -0
  109. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners.html.erb +42 -0
  110. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners.md +1 -0
  111. data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_table_react.jsx → _draggable_with_table.jsx} +1 -1
  112. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_table_react.md +3 -1
  113. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +10 -6
  114. data/app/pb_kits/playbook/pb_draggable/docs/index.js +4 -1
  115. data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +71 -3
  116. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableContainer.tsx +4 -3
  117. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +1 -1
  118. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +6 -6
  119. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.jsx +6 -6
  120. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.jsx +6 -6
  121. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +8 -8
  122. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +3 -3
  123. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +1 -1
  124. data/app/pb_kits/playbook/pb_form_group/_form_group.scss +45 -3
  125. data/app/pb_kits/playbook/pb_form_group/docs/_form_group_select.html.erb +15 -5
  126. data/app/pb_kits/playbook/pb_form_group/docs/_form_group_select.jsx +39 -6
  127. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_pb_styles.jsx +30 -0
  128. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_pb_styles.md +1 -0
  129. data/app/pb_kits/playbook/pb_gauge/docs/example.yml +1 -0
  130. data/app/pb_kits/playbook/pb_gauge/docs/index.js +1 -0
  131. data/app/pb_kits/playbook/pb_gauge/gaugeTheme.ts +85 -0
  132. data/app/pb_kits/playbook/pb_icon/icon.test.js +9 -9
  133. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.test.js +1 -1
  134. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.test.js +1 -1
  135. data/app/pb_kits/playbook/pb_icon_value/icon_value.test.js +1 -1
  136. data/app/pb_kits/playbook/pb_label_value/label_value.test.js +1 -1
  137. data/app/pb_kits/playbook/pb_layout/_layout.scss +127 -0
  138. data/app/pb_kits/playbook/pb_layout/_layout.tsx +47 -7
  139. data/app/pb_kits/playbook/pb_layout/docs/_layout_bracket.jsx +394 -0
  140. data/app/pb_kits/playbook/pb_layout/docs/_layout_bracket.md +5 -0
  141. data/app/pb_kits/playbook/pb_layout/docs/example.yml +1 -0
  142. data/app/pb_kits/playbook/pb_layout/docs/index.js +1 -0
  143. data/app/pb_kits/playbook/pb_layout/layout.test.js +4 -0
  144. data/app/pb_kits/playbook/pb_layout/subcomponents/_game.tsx +121 -0
  145. data/app/pb_kits/playbook/pb_layout/subcomponents/_participant.tsx +79 -0
  146. data/app/pb_kits/playbook/pb_layout/subcomponents/_round.tsx +74 -0
  147. data/app/pb_kits/playbook/pb_link/link.test.jsx +2 -2
  148. data/app/pb_kits/playbook/pb_nav/_nav_item.test.js +5 -3
  149. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +83 -22
  150. data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +39 -7
  151. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_color.jsx +63 -0
  152. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_color.md +3 -0
  153. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_default.md +1 -7
  154. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_fullscreen_background.jsx +49 -0
  155. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_fullscreen_background.md +1 -0
  156. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_fullscreen_opacity.jsx +81 -0
  157. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_fullscreen_opacity.md +1 -0
  158. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_gradient_opacity.jsx +39 -0
  159. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_gradient_opacity.md +1 -0
  160. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_layout.jsx +40 -0
  161. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_layout.md +5 -0
  162. data/app/pb_kits/playbook/pb_overlay/docs/example.yml +5 -0
  163. data/app/pb_kits/playbook/pb_overlay/docs/index.js +5 -0
  164. data/app/pb_kits/playbook/pb_overlay/overlay.test.jsx +39 -1
  165. data/app/pb_kits/playbook/pb_section_separator/docs/_section_separator_vertical.md +1 -0
  166. data/app/pb_kits/playbook/pb_stat_change/stat_change.test.js +8 -4
  167. data/app/pb_kits/playbook/pb_table/_table.tsx +2 -2
  168. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows.md +3 -1
  169. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_rows_rails.md +3 -1
  170. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table.md +3 -1
  171. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_nested_table_rails.md +3 -1
  172. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless.html.erb +34 -0
  173. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless_rails.md +1 -0
  174. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating.html.erb +36 -0
  175. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating_rails.md +1 -0
  176. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating_react.md +1 -1
  177. data/app/pb_kits/playbook/pb_table/docs/example.yml +2 -0
  178. data/app/pb_kits/playbook/pb_table/styles/_collapsible.scss +1 -1
  179. data/app/pb_kits/playbook/pb_table/styles/_headers.scss +19 -7
  180. data/app/pb_kits/playbook/pb_table/styles/_striped.scss +3 -3
  181. data/app/pb_kits/playbook/pb_table/table.rb +13 -1
  182. data/app/pb_kits/playbook/pb_table/table_header.rb +13 -1
  183. data/app/pb_kits/playbook/pb_text_input/_text_input.tsx +13 -5
  184. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_sanitize.jsx +94 -0
  185. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_sanitize.md +1 -0
  186. data/app/pb_kits/playbook/pb_text_input/docs/example.yml +2 -0
  187. data/app/pb_kits/playbook/pb_text_input/docs/index.js +1 -0
  188. data/app/pb_kits/playbook/pb_text_input/inputMask.ts +8 -1
  189. data/app/pb_kits/playbook/pb_tooltip/tooltip.html.erb +2 -5
  190. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_highlight.jsx +4 -4
  191. data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +2 -5
  192. data/app/pb_kits/playbook/pb_user/user.html.erb +1 -6
  193. data/app/pb_kits/playbook/pb_user_badge/user_badge.html.erb +1 -6
  194. data/dist/chunks/_typeahead-BX8IifKY.js +22 -0
  195. data/dist/chunks/_weekday_stacked-DfMD7HJz.js +45 -0
  196. data/dist/chunks/lib-96_ZmvAo.js +29 -0
  197. data/dist/chunks/{pb_form_validation-BvNy9Bd6.js → pb_form_validation-Vv2TqXVC.js} +1 -1
  198. data/dist/chunks/vendor.js +1 -1
  199. data/dist/menu.yml +2 -2
  200. data/dist/playbook-doc.js +19 -1
  201. data/dist/playbook-rails-react-bindings.js +1 -1
  202. data/dist/playbook-rails.js +1 -1
  203. data/dist/playbook.css +1 -1
  204. data/lib/playbook/kit_base.rb +4 -4
  205. data/lib/playbook/version.rb +2 -2
  206. metadata +79 -18
  207. data/dist/chunks/_typeahead-Djo6qCne.js +0 -22
  208. data/dist/chunks/_weekday_stacked-DIIHW0OV.js +0 -45
  209. data/dist/chunks/lib-BGzBzFZX.js +0 -29
  210. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_default_rails.html.erb → _draggable_default.html.erb} +0 -0
  211. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_default.md → _draggable_default_react.md} +0 -0
  212. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_multiple_containers_rails.html.erb → _draggable_multiple_containers.html.erb} +0 -0
  213. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_multiple_containers.md → _draggable_multiple_containers_react.md} +0 -0
  214. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_cards_rails.html.erb → _draggable_with_cards.html.erb} +0 -0
  215. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_cards.md → _draggable_with_cards_react.md} +0 -0
  216. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_list_rails.html.erb → _draggable_with_list.html.erb} +0 -0
  217. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_list.md → _draggable_with_list_react.md} +0 -0
  218. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_selectable_list_rails.html.erb → _draggable_with_selectable_list.html.erb} +0 -0
  219. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_selectable_list.md → _draggable_with_selectable_list_react.md} +0 -0
  220. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_table.md → _draggable_with_table_rails.md} +0 -0
@@ -53,4 +53,42 @@ $pb_button_styles: (
53
53
  }
54
54
  }
55
55
  }
56
- }
56
+ &.size_small {
57
+ @each $style in $pb_button_styles {
58
+ [class^=pb_button_kit][class*=_#{$style}] {
59
+ width: 20px;
60
+ height: 20px;
61
+ min-height: 20px;
62
+ border-radius: 10px;
63
+ line-height: 20px;
64
+ flex-basis: 20px;
65
+ min-width: 20px;
66
+ padding: 0;
67
+ }
68
+ }
69
+ // centering small icon svg
70
+ .pb_button_content {
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ // rails
75
+ svg.pb_custom_icon {
76
+ height: 14px;
77
+ width: 14px;
78
+ vertical-align: middle;
79
+ }
80
+ // react (nested within an additional span)
81
+ > span {
82
+ display: flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ > svg.pb_custom_icon {
86
+ height: 14px;
87
+ width: 14px;
88
+ vertical-align: middle;
89
+ display: inline-block;
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
@@ -22,6 +22,7 @@ type CircleIconButtonProps = {
22
22
  type?: 'button' | 'submit' | 'reset' | undefined,
23
23
  target?: string
24
24
  variant?: 'primary' | 'secondary' | 'link',
25
+ size?: 'default' | 'sm',
25
26
  }
26
27
 
27
28
  const CircleIconButton = (props: CircleIconButtonProps): React.ReactElement => {
@@ -41,13 +42,16 @@ const CircleIconButton = (props: CircleIconButtonProps): React.ReactElement => {
41
42
  link,
42
43
  newWindow,
43
44
  variant,
45
+ size = 'default',
44
46
  } = props
45
47
 
46
48
  const ariaProps = buildAriaProps(aria)
47
49
  const dataProps = buildDataProps(data)
48
50
  const htmlProps = buildHtmlProps(htmlOptions)
51
+ const sizeClass = size === 'sm' ? 'size_small' : ''
49
52
  const classes = classnames(
50
53
  buildCss('pb_circle_icon_button_kit'),
54
+ sizeClass,
51
55
  globalProps(props),
52
56
  className
53
57
  )
@@ -18,8 +18,16 @@ module Playbook
18
18
  prop :new_window, type: Playbook::Props::Boolean,
19
19
  default: false
20
20
  prop :target
21
+ prop :size, type: Playbook::Props::Enum,
22
+ values: %w[default sm],
23
+ default: "default"
24
+
21
25
  def classname
22
- generate_classname("pb_circle_icon_button_kit")
26
+ generate_classname("pb_circle_icon_button_kit") + size_class
27
+ end
28
+
29
+ def size_class
30
+ size == "sm" ? " size_small" : ""
23
31
  end
24
32
  end
25
33
  end
@@ -30,3 +30,17 @@ test('passes loading prop to button', () => {
30
30
 
31
31
  expect(button).toBeInTheDocument()
32
32
  })
33
+
34
+ test('adds size_small class when size is sm', () => {
35
+ render(
36
+ <CircleIconButton
37
+ data={{ testid: 'small-size-test' }}
38
+ icon="plus"
39
+ size="sm"
40
+ />
41
+ )
42
+
43
+ const kit = screen.getByTestId('small-size-test')
44
+
45
+ expect(kit).toHaveClass('pb_circle_icon_button_kit size_small')
46
+ })
@@ -0,0 +1,28 @@
1
+ <%= pb_rails("flex", props: { orientation: "column", gap: "sm" }) do %>
2
+ <%= pb_rails("circle_icon_button", props: {
3
+ icon: "plus",
4
+ size: "sm",
5
+ variant: "primary"
6
+ }) %>
7
+
8
+ <%= pb_rails("circle_icon_button", props: {
9
+ icon: "pen",
10
+ loading: true,
11
+ size: "sm",
12
+ variant: "secondary"
13
+ }) %>
14
+
15
+ <%= pb_rails("circle_icon_button", props: {
16
+ disabled: true,
17
+ icon: "times",
18
+ size: "sm"
19
+ }) %>
20
+
21
+ <%= pb_rails("circle_icon_button", props: {
22
+ icon: "info",
23
+ link: "https://playbook.powerapp.cloud/",
24
+ size: "sm",
25
+ target: "child",
26
+ variant: "link"
27
+ }) %>
28
+ <% end %>
@@ -0,0 +1,42 @@
1
+ import React from 'react'
2
+
3
+ import CircleIconButton from '../_circle_icon_button'
4
+ import Flex from '../../pb_flex/_flex'
5
+
6
+ const CircleIconButtonSize = (props) => (
7
+ <>
8
+ <Flex gap="sm"
9
+ orientation="column"
10
+ >
11
+ <CircleIconButton
12
+ icon="plus"
13
+ size="sm"
14
+ variant="primary"
15
+ {...props}
16
+ />
17
+ <CircleIconButton
18
+ icon="pen"
19
+ loading
20
+ size="sm"
21
+ variant="secondary"
22
+ {...props}
23
+ />
24
+ <CircleIconButton
25
+ disabled
26
+ icon="times"
27
+ size="sm"
28
+ {...props}
29
+ />
30
+ <CircleIconButton
31
+ icon="info"
32
+ link="https://playbook.powerapp.cloud/"
33
+ size="sm"
34
+ target="child"
35
+ variant="link"
36
+ {...props}
37
+ />
38
+ </Flex>
39
+ </>
40
+ )
41
+
42
+ export default CircleIconButtonSize
@@ -0,0 +1 @@
1
+ The `size` prop accepts "sm" as a value to make the Circle Icon Button 20px x 20px instead of the default 40px x 40px size.
@@ -4,9 +4,11 @@ examples:
4
4
  - circle_icon_button_default: Default
5
5
  - circle_icon_button_link: Link
6
6
  - circle_icon_button_loading: Loading
7
+ - circle_icon_button_size: Size
7
8
 
8
9
  react:
9
10
  - circle_icon_button_default: Default
10
11
  - circle_icon_button_click: Click Handler
11
12
  - circle_icon_button_link: Link
12
13
  - circle_icon_button_loading: Loading
14
+ - circle_icon_button_size: Size
@@ -2,3 +2,4 @@ export { default as CircleIconButtonDefault } from './_circle_icon_button_defaul
2
2
  export { default as CircleIconButtonClick } from './_circle_icon_button_click.jsx'
3
3
  export { default as CircleIconButtonLink } from './_circle_icon_button_link.jsx'
4
4
  export { default as CircleIconButtonLoading } from './_circle_icon_button_loading.jsx'
5
+ export { default as CircleIconButtonSize } from './_circle_icon_button_size.jsx'
@@ -27,13 +27,20 @@ exports[`html structure is correct 1`] = `
27
27
  class="icon_wrapper"
28
28
  style="vertical-align: middle; color: rgb(193, 205, 214);"
29
29
  >
30
- <i
31
- class="pb_icon_kit far fa-lg fa-fw fa-lg fa-chevron-down"
32
- />
33
- <span
34
- aria-label="chevron-down icon"
35
- hidden=""
36
- />
30
+ <svg
31
+ class="pb_custom_icon svg-inline--fa svg_lg svg_fw"
32
+ color="currentColor"
33
+ fill="none"
34
+ height="auto"
35
+ viewBox="0 0 30 25"
36
+ width="auto"
37
+ xmlns="http://www.w3.org/2000/svg"
38
+ >
39
+ <path
40
+ d="M14.203 19.297l-9-9c-.469-.422-.469-1.125 0-1.594.422-.422 1.125-.422 1.594 0L15 16.953l8.203-8.203c.422-.469 1.125-.469 1.594 0a1.103 1.103 0 010 1.547l-9.047 9a1.027 1.027 0 01-1.547 0z"
41
+ fill="#242B42"
42
+ />
43
+ </svg>
37
44
  </div>
38
45
  </div>
39
46
  </div>
@@ -75,15 +75,15 @@ test('returns correct icon', () => {
75
75
  </>
76
76
  )
77
77
 
78
- expect(screen.getByTestId('test-cell').querySelector('.pb_icon_kit')).toHaveClass('fa-mobile')
79
- expect(screen.getByTestId('test-home').querySelector('.pb_icon_kit')).toHaveClass('fa-phone')
78
+ expect(screen.getByTestId('test-cell').querySelector('.pb_custom_icon')).toBeInTheDocument()
79
+ expect(screen.getByTestId('test-home').querySelector('.pb_custom_icon')).toBeInTheDocument()
80
80
  expect(screen.getByTestId('test-work').querySelector('.pb_icon_kit')).toHaveClass('fa-phone-office')
81
- expect(screen.getByTestId('test-work-cell').querySelector('.pb_icon_kit')).toHaveClass('fa-phone-laptop')
82
- expect(screen.getByTestId('test-email').querySelector('.pb_custom_icon')).toHaveClass('envelope')
83
- expect(screen.getByTestId('test-wrong-phone').querySelector('.pb_icon_kit')).toHaveClass('fa-phone-slash')
84
- expect(screen.getByTestId('test-wrong-type').querySelector('.pb_icon_kit')).toHaveClass('fa-phone')
81
+ expect(screen.getByTestId('test-work-cell').querySelector('.pb_custom_icon')).toBeInTheDocument()
82
+ expect(screen.getByTestId('test-email').querySelector('.pb_custom_icon')).toBeInTheDocument()
83
+ expect(screen.getByTestId('test-wrong-phone').querySelector('.pb_custom_icon')).toBeInTheDocument()
84
+ expect(screen.getByTestId('test-wrong-type').querySelector('.pb_custom_icon')).toBeInTheDocument()
85
85
  expect(screen.getByTestId('test-extension').querySelector('.pb_icon_kit')).toHaveClass('fa-phone-plus')
86
- expect(screen.getByTestId('test-empty').querySelector('.pb_icon_kit')).toHaveClass('fa-phone')
86
+ expect(screen.getByTestId('test-empty').querySelector('.pb_custom_icon')).toBeInTheDocument()
87
87
  })
88
88
 
89
89
  test("not compliant values return null in phone related contact types", () => {
@@ -1,5 +1,4 @@
1
-
2
- import React, { useState } from 'react'
1
+ import React from 'react'
3
2
  import classnames from 'classnames'
4
3
  import { buildAriaProps, buildCss, buildDataProps } from '../utilities/props'
5
4
  import { globalProps } from '../utilities/globalProps'
@@ -7,16 +6,19 @@ import { globalProps } from '../utilities/globalProps'
7
6
  import Button from '../pb_button/_button'
8
7
  import Tooltip from '../pb_tooltip/_tooltip'
9
8
 
9
+ import usePBCopy from './usePBCopy'
10
+
10
11
  type CopyButtonProps = {
11
- aria?: { [key: string]: string },
12
- className?: string,
13
- data?: { [key: string]: string },
14
- id?: string,
15
- from?: string,
16
- text?: string,
17
- tooltipPlacement?: "top" | "right" | "bottom" | "left",
18
- tooltipText?: string,
19
- value?: string,
12
+ aria?: { [key: string]: string }
13
+ className?: string
14
+ data?: { [key: string]: string }
15
+ id?: string
16
+ from?: string
17
+ text?: string
18
+ tooltipPlacement?: 'top' | 'right' | 'bottom' | 'left'
19
+ tooltipText?: string
20
+ value?: string
21
+ timeout?: number
20
22
  }
21
23
 
22
24
  const CopyButton = (props: CopyButtonProps) => {
@@ -27,62 +29,34 @@ const CopyButton = (props: CopyButtonProps) => {
27
29
  from = '',
28
30
  id,
29
31
  text= 'Copy',
32
+ timeout = 1000,
30
33
  tooltipPlacement= 'bottom',
31
34
  tooltipText = 'Copied!',
32
35
  value = '',
33
36
  } = props
34
37
 
35
- const [copied, setCopied] = useState(false)
38
+ const [copied, copy] = usePBCopy({ value, from, timeout })
36
39
 
37
40
  const ariaProps = buildAriaProps(aria)
38
41
  const dataProps = buildDataProps(data)
39
42
  const classes = classnames(buildCss('pb_copy_button_kit'), globalProps(props), className)
40
43
 
41
- const copy = () => {
42
- if (!from && !value) {
43
- return
44
- }
45
-
46
- if (value) {
47
- navigator.clipboard.writeText(value)
48
- } else if (from) {
49
- const copyElement = document.getElementById(from);
50
- let copyText = copyElement?.innerText
51
-
52
- if (copyElement instanceof HTMLTextAreaElement || copyElement instanceof HTMLInputElement) {
53
- copyText = copyElement.value;
54
- }
55
-
56
- if (copyText) {
57
- navigator.clipboard.writeText(copyText)
58
- }
59
- }
60
-
61
- setCopied(true)
62
-
63
- setTimeout(() => {
64
- setCopied(false)
65
- }, 1000);
66
- }
67
-
68
44
  return (
69
- <div
70
- {...ariaProps}
45
+ <div {...ariaProps}
71
46
  {...dataProps}
72
47
  className={classes}
73
48
  id={id}
74
49
  >
75
- <Tooltip
50
+ <Tooltip
76
51
  forceOpenTooltip={copied}
77
52
  placement={tooltipPlacement}
78
53
  showTooltip={false}
79
54
  text={tooltipText}
80
55
  >
81
- <Button
82
- icon='copy'
56
+ <Button icon="copy"
83
57
  onClick={copy}
84
58
  >
85
- { text }
59
+ {text}
86
60
  </Button>
87
61
  </Tooltip>
88
62
  </div>
@@ -0,0 +1,54 @@
1
+ import React, { useEffect, useState } from 'react'
2
+ import usePBCopy from '../../pb_copy_button/usePBCopy'
3
+ import Body from '../../pb_body/_body'
4
+ import Textarea from '../../pb_textarea/_textarea'
5
+ import Tooltip from '../../pb_tooltip/_tooltip'
6
+
7
+ const CopyButtonHook = ({...props}) => {
8
+ // This is how you can use the copy button hook to copy text to the clipboard
9
+ // eslint-disable-next-line no-unused-vars
10
+ const [copied, copyToClipboard] = usePBCopy({ from: 'hookbody' })
11
+ // I added a tooltip so it looks better in the ui
12
+ const [showTooltip, setShowTooltip] = useState(false)
13
+
14
+ const handleCopy = () => {
15
+ copyToClipboard()
16
+ setShowTooltip(true)
17
+ setTimeout(() => setShowTooltip(false), 1500)
18
+ }
19
+
20
+ useEffect(() => {
21
+ const el = document.getElementById('hookbody')
22
+ if (!el) return
23
+
24
+ el.addEventListener('click', handleCopy)
25
+ return () => {
26
+ el.removeEventListener('click', handleCopy)
27
+ }
28
+ }, [copyToClipboard])
29
+
30
+ return (
31
+ <div>
32
+ <Tooltip
33
+ delay={{ close: 1000 }}
34
+ forceOpenTooltip={showTooltip}
35
+ placement="top"
36
+ showTooltip={false}
37
+ text="Copied!"
38
+ >
39
+ <Body
40
+ cursor="pointer"
41
+ id="hookbody"
42
+ text="I'm a custom copy hook! Click this body to copy this text!"
43
+ />
44
+ </Tooltip>
45
+
46
+ <Textarea
47
+ {...props}
48
+ placeholder="Paste here"
49
+ />
50
+ </div>
51
+ )
52
+ }
53
+
54
+ export default CopyButtonHook
@@ -0,0 +1,3 @@
1
+ We provide a `usePBCopy` hook that you can import to your project. This hook will return a function that you can call to copy the text to the clipboard.
2
+
3
+ `usePBCopy({ from: 'your_id' })` will grab the `innerText` from `your_id` element, or `value` if it is an input element.
@@ -0,0 +1,14 @@
1
+ <%= pb_rails("body", props: { cursor: "pointer", data: { "external-copy-from": "hookbody"} }) do %>
2
+ <span id="hookbody">I'm a custom copy hook! Click this body to copy this text!</span>
3
+ <% end %>
4
+
5
+ <%= pb_rails("tooltip", props: {
6
+ trigger_element_selector: "#hookbody",
7
+ tooltip_id: "hookbody_tooltip",
8
+ position: 'top',
9
+ trigger_method: "click"
10
+ }) do %>
11
+ Copied!
12
+ <% end %>
13
+
14
+ <%= pb_rails("textarea", props: { margin_top: "xs", placeholder: "Paste here" }) %>
@@ -0,0 +1,3 @@
1
+ You can use any external control (like the text itself or an icon) to copy. To use this hook, set the `data-external-copy-from` attribute on the external control to the copying ID. This will grab the `innerText` from `your_id` element, or `value` if it is an input element. Alternatively, you can set a `data-external-copy-value` attribute and copy custom text.
2
+
3
+ See the code example for details.
@@ -2,7 +2,9 @@ examples:
2
2
  rails:
3
3
  - copy_button_default: Default
4
4
  - copy_button_from: Copy From
5
+ - copy_button_hook_rails: Copy Hook
5
6
 
6
7
  react:
7
8
  - copy_button_default: Default
8
9
  - copy_button_from: Copy From
10
+ - copy_button_hook: Copy Hook
@@ -1,2 +1,3 @@
1
1
  export { default as CopyButtonDefault } from './_copy_button_default.jsx'
2
- export { default as CopyButtonFrom } from './_copy_button_from.jsx'
2
+ export { default as CopyButtonFrom } from './_copy_button_from.jsx'
3
+ export { default as CopyButtonHook } from './_copy_button_hook.jsx'
@@ -1,6 +1,33 @@
1
1
  import PbEnhancedElement from "../pb_enhanced_element"
2
2
 
3
- export default class PbCopyButton extends PbEnhancedElement {
3
+ function getTextFromElement(element) {
4
+ if (!element) return ''
5
+ return element.tagName.toLowerCase() === 'input'
6
+ ? element.value
7
+ : element.innerText
8
+ }
9
+
10
+ function copyTextToClipboard(text) {
11
+ if (!text) return
12
+ navigator.clipboard.writeText(text)
13
+ .catch(err => console.error('Failed to copy text:', err))
14
+ }
15
+
16
+ function handleExternalControlCopyClick(element) {
17
+ const value = element.getAttribute('data-external-copy-value')
18
+ const fromId = element.getAttribute('data-external-copy-from')
19
+
20
+ if (value) {
21
+ copyTextToClipboard(value)
22
+ } else if (fromId) {
23
+ const fromElement = document.querySelector(`#${fromId}`)
24
+ copyTextToClipboard(getTextFromElement(fromElement))
25
+ } else {
26
+ console.warn('Failed to copy:', element)
27
+ }
28
+ }
29
+
30
+ export class PbCopyButton extends PbEnhancedElement {
4
31
  static get selector() {
5
32
  return '.pb_copy_button_kit'
6
33
  }
@@ -20,28 +47,27 @@ export default class PbCopyButton extends PbEnhancedElement {
20
47
  }
21
48
 
22
49
  handleClick() {
50
+ const value = this.element.getAttribute('data-copy-value')
23
51
  const fromId = this.element.getAttribute('data-from')
24
- if (fromId) {
25
- const fromElement = document.querySelector(`#${fromId}`)
26
- if (fromElement) {
27
- let contentToCopy = ''
28
- if (fromElement.tagName.toLowerCase() === 'input') {
29
- contentToCopy = fromElement.value
30
- } else {
31
- contentToCopy = fromElement.innerText
32
- }
33
- navigator.clipboard.writeText(contentToCopy)
34
- .catch(err => console.error('Failed to copy text', err))
35
- return
36
- }
37
- }
38
52
 
39
- const textToCopy = this.element.getAttribute('data-copy-value')
40
- if (textToCopy) {
41
- navigator.clipboard.writeText(textToCopy)
42
- .catch(err => console.error('Failed to copy text', err))
53
+ if (value) {
54
+ copyTextToClipboard(value)
55
+ } else if (fromId) {
56
+ const fromElement = document.querySelector(`#${fromId}`)
57
+ copyTextToClipboard(getTextFromElement(fromElement))
43
58
  } else {
44
- console.warn('No data-copy-value attribute found or data-from element')
59
+ console.warn('No data-copy-value or data-from attribute found')
45
60
  }
46
61
  }
47
62
  }
63
+
64
+ export function addCopyEventListeners() {
65
+ const externalCopyElements = [
66
+ ...document.querySelectorAll('div[data-external-copy-value]'),
67
+ ...document.querySelectorAll('div[data-external-copy-from]')
68
+ ]
69
+
70
+ externalCopyElements.forEach(element => {
71
+ element.addEventListener('click', () => handleExternalControlCopyClick(element))
72
+ })
73
+ }
@@ -0,0 +1,45 @@
1
+ import { useState, useRef, useEffect } from 'react'
2
+
3
+ type UsePBCopyProps = {
4
+ value?: string
5
+ from?: string
6
+ timeout?: number
7
+ }
8
+
9
+ export default function usePBCopy({
10
+ value = '',
11
+ from = '',
12
+ timeout = 0,
13
+ }: UsePBCopyProps) {
14
+ const [copied, setCopied] = useState(false)
15
+ const timerRef = useRef<number>()
16
+
17
+ const copy = () => {
18
+ if (!value && !from) return
19
+
20
+ if (value) {
21
+ navigator.clipboard.writeText(value)
22
+ } else {
23
+ const el = document.getElementById(from)
24
+ let text = el?.innerText
25
+ if (el instanceof HTMLTextAreaElement || el instanceof HTMLInputElement) {
26
+ text = el.value
27
+ }
28
+ if (text) navigator.clipboard.writeText(text)
29
+ }
30
+
31
+ setCopied(true)
32
+ window.clearTimeout(timerRef.current)
33
+ timerRef.current = window.setTimeout(() => {
34
+ setCopied(false)
35
+ }, timeout)
36
+ }
37
+
38
+ useEffect(() => {
39
+ return () => {
40
+ window.clearTimeout(timerRef.current)
41
+ }
42
+ }, [])
43
+
44
+ return [copied, copy] as const
45
+ }
@@ -50,6 +50,10 @@ type DatePickerProps = {
50
50
  timeFormat?: string,
51
51
  type?: string,
52
52
  yearRange?: number[],
53
+ controlsStartId?: string,
54
+ controlsEndId?: string,
55
+ syncStartWith?: string,
56
+ syncEndWith?: string,
53
57
  } & GlobalProps
54
58
 
55
59
  const DatePicker = (props: DatePickerProps): React.ReactElement => {
@@ -98,6 +102,10 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
98
102
  staticPosition = true,
99
103
  thisRangesEndToday = false,
100
104
  yearRange = [1900, 2100],
105
+ controlsStartId,
106
+ controlsEndId,
107
+ syncStartWith,
108
+ syncEndWith,
101
109
  } = props
102
110
 
103
111
  const ariaProps = buildAriaProps(aria)
@@ -134,6 +142,10 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
134
142
  staticPosition,
135
143
  thisRangesEndToday,
136
144
  yearRange,
145
+ controlsStartId,
146
+ controlsEndId,
147
+ syncStartWith,
148
+ syncEndWith,
137
149
  required: false,
138
150
  }, scrollContainer)
139
151
  }, initializeOnce ? [] : undefined)
@@ -77,6 +77,14 @@ module Playbook
77
77
  default: ""
78
78
  prop :validation_message, type: Playbook::Props::String,
79
79
  default: ""
80
+ prop :controls_start_id, type: Playbook::Props::String,
81
+ default: ""
82
+ prop :controls_end_id, type: Playbook::Props::String,
83
+ default: ""
84
+ prop :sync_start_with, type: Playbook::Props::String,
85
+ default: ""
86
+ prop :sync_end_with, type: Playbook::Props::String,
87
+ default: ""
80
88
 
81
89
  def classname
82
90
  default_margin_bottom = margin_bottom.present? ? "" : " mb_sm"
@@ -108,6 +116,10 @@ module Playbook
108
116
  staticPosition: static_position,
109
117
  thisRangesEndToday: this_ranges_end_today,
110
118
  yearRange: year_range,
119
+ controlsStartId: controls_start_id,
120
+ controlsEndId: controls_end_id,
121
+ syncStartWith: sync_start_with,
122
+ syncEndWith: sync_end_with,
111
123
  }.to_json.html_safe
112
124
  end
113
125