playbook_ui 14.16.0 → 14.17.0.pre.alpha.PBNTR766tablenestedcollapsiblerowsborderdoubling7256

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 (163) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Utilities/types.ts +1 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +104 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +168 -85
  5. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +2 -2
  6. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +10 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +20 -7
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.jsx +90 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.md +3 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.jsx +0 -1
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.html.erb +39 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.html.erb +33 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows_rails.md +1 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.md +6 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +4 -1
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -1
  17. data/app/pb_kits/playbook/pb_advanced_table/index.js +1 -1
  18. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +4 -2
  19. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +19 -9
  20. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +38 -1
  21. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +49 -37
  22. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +39 -0
  23. data/app/pb_kits/playbook/pb_background/_background.scss +26 -0
  24. data/app/pb_kits/playbook/pb_background/_background.tsx +5 -3
  25. data/app/pb_kits/playbook/pb_background/background.test.js +5 -0
  26. data/app/pb_kits/playbook/pb_background/docs/_background_overlay.jsx +35 -0
  27. data/app/pb_kits/playbook/pb_background/docs/_background_overlay.md +1 -0
  28. data/app/pb_kits/playbook/pb_background/docs/example.yml +1 -0
  29. data/app/pb_kits/playbook/pb_background/docs/index.js +1 -0
  30. data/app/pb_kits/playbook/pb_button/_button.scss +5 -5
  31. data/app/pb_kits/playbook/pb_collapsible/__snapshots__/collapsible.test.js.snap +14 -7
  32. data/app/pb_kits/playbook/pb_contact/contact.test.js +7 -7
  33. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +34 -34
  34. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +2 -2
  35. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +16 -0
  36. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.html.erb +0 -11
  37. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.jsx +0 -7
  38. data/app/pb_kits/playbook/pb_date_picker/sass_partials/_inline_styles.scss +28 -24
  39. data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.test.js +2 -2
  40. data/app/pb_kits/playbook/pb_date_range_stacked/date_range_stacked.test.js +1 -1
  41. data/app/pb_kits/playbook/pb_draggable/_draggable.scss +43 -20
  42. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +58 -17
  43. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.jsx +102 -105
  44. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.md +3 -3
  45. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.jsx +50 -48
  46. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_colors.md +1 -1
  47. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line.jsx +110 -0
  48. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line.md +5 -0
  49. data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_table_react.jsx → _draggable_with_table.jsx} +1 -1
  50. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_table_react.md +3 -1
  51. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +9 -6
  52. data/app/pb_kits/playbook/pb_draggable/docs/index.js +4 -1
  53. data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +71 -3
  54. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableContainer.tsx +4 -3
  55. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +6 -6
  56. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.jsx +6 -6
  57. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.jsx +6 -6
  58. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +8 -8
  59. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +3 -3
  60. data/app/pb_kits/playbook/pb_filter/Filter/CurrentFilters.tsx +3 -4
  61. data/app/pb_kits/playbook/pb_filter/Filter/SortMenu.tsx +2 -3
  62. data/app/pb_kits/playbook/pb_form/pb_form_validation.js +1 -1
  63. data/app/pb_kits/playbook/pb_form_group/_form_group.scss +40 -2
  64. data/app/pb_kits/playbook/pb_form_group/docs/_form_group_select.html.erb +15 -5
  65. data/app/pb_kits/playbook/pb_form_group/docs/_form_group_select.jsx +20 -5
  66. data/app/pb_kits/playbook/pb_icon/icon.test.js +9 -9
  67. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.test.js +1 -1
  68. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.test.js +1 -1
  69. data/app/pb_kits/playbook/pb_icon_value/icon_value.test.js +1 -1
  70. data/app/pb_kits/playbook/pb_label_value/label_value.test.js +1 -1
  71. data/app/pb_kits/playbook/pb_layout/_layout.scss +127 -0
  72. data/app/pb_kits/playbook/pb_layout/_layout.tsx +47 -7
  73. data/app/pb_kits/playbook/pb_layout/docs/_layout_bracket.jsx +394 -0
  74. data/app/pb_kits/playbook/pb_layout/docs/_layout_bracket.md +5 -0
  75. data/app/pb_kits/playbook/pb_layout/docs/example.yml +1 -0
  76. data/app/pb_kits/playbook/pb_layout/docs/index.js +1 -0
  77. data/app/pb_kits/playbook/pb_layout/layout.test.js +4 -0
  78. data/app/pb_kits/playbook/pb_layout/subcomponents/_game.tsx +121 -0
  79. data/app/pb_kits/playbook/pb_layout/subcomponents/_participant.tsx +79 -0
  80. data/app/pb_kits/playbook/pb_layout/subcomponents/_round.tsx +74 -0
  81. data/app/pb_kits/playbook/pb_lightbox/hooks/useVisibility.js +1 -1
  82. data/app/pb_kits/playbook/pb_link/link.test.jsx +2 -2
  83. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -1
  84. data/app/pb_kits/playbook/pb_nav/_nav_item.test.js +5 -3
  85. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +49 -22
  86. data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +15 -4
  87. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_color.jsx +63 -0
  88. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_color.md +3 -0
  89. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_default.md +1 -7
  90. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_gradient_opacity.jsx +39 -0
  91. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_gradient_opacity.md +1 -0
  92. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_layout.jsx +40 -0
  93. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_layout.md +5 -0
  94. data/app/pb_kits/playbook/pb_overlay/docs/example.yml +3 -0
  95. data/app/pb_kits/playbook/pb_overlay/docs/index.js +3 -0
  96. data/app/pb_kits/playbook/pb_overlay/overlay.test.jsx +39 -1
  97. data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +29 -11
  98. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_default.html.erb +1 -1
  99. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb +4 -4
  100. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb +2 -0
  101. data/app/pb_kits/playbook/pb_section_separator/docs/_section_separator_vertical.md +1 -0
  102. data/app/pb_kits/playbook/pb_stat_change/stat_change.test.js +8 -4
  103. data/app/pb_kits/playbook/pb_table/_table.tsx +4 -0
  104. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless.html.erb +34 -0
  105. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless.jsx +50 -0
  106. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless_rails.md +1 -0
  107. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_borderless_react.md +1 -0
  108. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating.html.erb +36 -0
  109. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating.jsx +59 -0
  110. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating_rails.md +1 -0
  111. data/app/pb_kits/playbook/pb_table/docs/_table_with_header_style_floating_react.md +1 -0
  112. data/app/pb_kits/playbook/pb_table/docs/example.yml +4 -0
  113. data/app/pb_kits/playbook/pb_table/docs/index.js +2 -0
  114. data/app/pb_kits/playbook/pb_table/styles/_collapsible.scss +84 -0
  115. data/app/pb_kits/playbook/pb_table/styles/_headers.scss +89 -1
  116. data/app/pb_kits/playbook/pb_table/styles/_striped.scss +3 -3
  117. data/app/pb_kits/playbook/pb_table/subcomponents/_table_head.tsx +11 -1
  118. data/app/pb_kits/playbook/pb_table/subcomponents/_table_header.tsx +11 -1
  119. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +5 -0
  120. data/app/pb_kits/playbook/pb_table/table.rb +13 -1
  121. data/app/pb_kits/playbook/pb_table/table.test.js +17 -0
  122. data/app/pb_kits/playbook/pb_table/table_header.rb +13 -1
  123. data/app/pb_kits/playbook/pb_tooltip/index.js +183 -56
  124. data/app/pb_kits/playbook/pb_tooltip/tooltip.html.erb +2 -5
  125. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_highlight.jsx +4 -4
  126. data/app/pb_kits/playbook/pb_typeahead/index.ts +2 -2
  127. data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +2 -5
  128. data/app/pb_kits/playbook/pb_user/user.html.erb +1 -6
  129. data/app/pb_kits/playbook/pb_user_badge/user_badge.html.erb +1 -6
  130. data/app/pb_kits/playbook/utilities/globalProps.ts +1 -1
  131. data/app/pb_kits/playbook/utilities/object.test.js +149 -1
  132. data/app/pb_kits/playbook/utilities/object.ts +124 -42
  133. data/dist/chunks/_typeahead-BY6AFq1l.js +22 -0
  134. data/dist/chunks/_weekday_stacked-DvC4wBNS.js +45 -0
  135. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  136. data/dist/chunks/lib-BGzBzFZX.js +29 -0
  137. data/dist/chunks/{pb_form_validation-DMajaRt3.js → pb_form_validation-BvNy9Bd6.js} +1 -1
  138. data/dist/chunks/vendor.js +1 -1
  139. data/dist/playbook-doc.js +1 -1
  140. data/dist/playbook-rails-react-bindings.js +1 -1
  141. data/dist/playbook-rails.js +1 -1
  142. data/dist/playbook.css +1 -1
  143. data/lib/playbook/kit_base.rb +4 -4
  144. data/lib/playbook/version.rb +2 -2
  145. metadata +51 -22
  146. data/app/pb_kits/playbook/pb_tooltip/floating_ui.js +0 -282
  147. data/dist/chunks/_typeahead-BuTZG1Jn.js +0 -22
  148. data/dist/chunks/_weekday_stacked-oT22q75-.js +0 -45
  149. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
  150. data/dist/chunks/lib-Co5y3V4K.js +0 -29
  151. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows.md → _advanced_table_selectable_rows_no_subrows_react.md} +0 -0
  152. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows.md → _advanced_table_selectable_rows_react.md} +0 -0
  153. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_default_rails.html.erb → _draggable_default.html.erb} +0 -0
  154. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_default.md → _draggable_default_react.md} +0 -0
  155. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_multiple_containers_rails.html.erb → _draggable_multiple_containers.html.erb} +0 -0
  156. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_multiple_containers.md → _draggable_multiple_containers_react.md} +0 -0
  157. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_cards_rails.html.erb → _draggable_with_cards.html.erb} +0 -0
  158. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_cards.md → _draggable_with_cards_react.md} +0 -0
  159. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_list_rails.html.erb → _draggable_with_list.html.erb} +0 -0
  160. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_list.md → _draggable_with_list_react.md} +0 -0
  161. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_selectable_list_rails.html.erb → _draggable_with_selectable_list.html.erb} +0 -0
  162. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_selectable_list.md → _draggable_with_selectable_list_react.md} +0 -0
  163. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_with_table.md → _draggable_with_table_rails.md} +0 -0
@@ -4,6 +4,10 @@ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../uti
4
4
 
5
5
  import { GlobalProps, globalProps, globalInlineProps } from '../utilities/globalProps'
6
6
 
7
+ import { Round, RoundLabel } from "./subcomponents/_round";
8
+ import Game from "./subcomponents/_game";
9
+ import Participant from "./subcomponents/_participant";
10
+
7
11
  type LayoutPropTypes = {
8
12
  aria?: {[key: string]: string},
9
13
  children?: React.ReactChild[] | React.ReactChild,
@@ -18,7 +22,7 @@ type LayoutPropTypes = {
18
22
  size?: "xs" | "sm" | "md" | "base" | "lg" | "xl",
19
23
  variant?: "light" | "dark" | "gradient",
20
24
  transparent?: boolean,
21
- layout?: "sidebar" | "collection" | "kanban" | "content" | "masonry",
25
+ layout?: "sidebar" | "collection" | "kanban" | "content" | "masonry" | "bracket",
22
26
  } & GlobalProps
23
27
 
24
28
  type LayoutSideProps = {
@@ -140,7 +144,7 @@ const Layout = (props: LayoutPropTypes) => {
140
144
  const htmlProps = buildHtmlProps(htmlOptions)
141
145
 
142
146
  const layoutCss =
143
- layout == 'collection'
147
+ (layout == 'collection' || layout == 'bracket')
144
148
  ? `pb_layout_kit_${layout}`
145
149
  : layout == 'kanban'
146
150
  ? `pb_layout_kit_${layout}${responsiveClass}`
@@ -151,11 +155,9 @@ const Layout = (props: LayoutPropTypes) => {
151
155
  })
152
156
 
153
157
  const layoutCollapseCss =
154
- layout == 'collection'
158
+ (layout == 'collection' || layout == 'kanban' || layout == 'bracket')
155
159
  ? ''
156
- : layout == 'kanban'
157
- ? ''
158
- : buildCss('layout', position, 'collapse', collapse)
160
+ : buildCss('layout', position, 'collapse', collapse)
159
161
 
160
162
  const layoutChildren = React.Children.toArray(children)
161
163
 
@@ -175,6 +177,40 @@ const Layout = (props: LayoutPropTypes) => {
175
177
  (child: React.ReactElement & {type: {displayName: string}}) => child.type?.displayName !== 'Side'
176
178
  )
177
179
 
180
+ const numberOfRounds = Array.isArray(children) ? React.Children.toArray(children).filter(
181
+ (child) => {
182
+ return (child as React.ReactElement).type === Layout.Round;
183
+ }
184
+ ).length : 0
185
+
186
+ const lastRoundWithSelf = React.Children.toArray(children).filter((child) => {
187
+ if ((child as React.ReactElement).type !== Layout.Round) {
188
+ return false
189
+ }
190
+
191
+ const roundElement = child as React.ReactElement
192
+
193
+ const gameChildren = React.Children.toArray(roundElement.props.children)
194
+
195
+ const hasWinningSelfParticipant = gameChildren.some((gameChild) => {
196
+ const gameElement = gameChild as React.ReactElement
197
+
198
+ const participantChildren = React.Children.toArray(gameElement.props.children)
199
+
200
+ return participantChildren.some((participantChild) => {
201
+ const participantElement = participantChild as React.ReactElement
202
+ const { self } = participantElement.props
203
+ return self === true
204
+ })
205
+ })
206
+
207
+ return hasWinningSelfParticipant
208
+ }).length
209
+
210
+ const bracketChildren = nonSideChildren.map(child =>
211
+ React.isValidElement(child) ? React.cloneElement(child, { numberOfRounds, lastRoundWithSelf }) : child
212
+ )
213
+
178
214
  const filteredProps = {...props}
179
215
  delete filteredProps?.position
180
216
 
@@ -196,7 +232,7 @@ const Layout = (props: LayoutPropTypes) => {
196
232
  style={dynamicInlineProps}
197
233
  >
198
234
  {subComponentTags('Side')}
199
- {nonSideChildren}
235
+ {layout === 'bracket' ? bracketChildren : nonSideChildren}
200
236
  </div>
201
237
  )
202
238
  }
@@ -206,5 +242,9 @@ Layout.Body = Body
206
242
  Layout.Item = Item
207
243
  Layout.Header = Header
208
244
  Layout.Footer = Footer
245
+ Layout.Round = Round
246
+ Layout.Game = Game
247
+ Layout.RoundLabel = RoundLabel
248
+ Layout.Participant = Participant
209
249
 
210
250
  export default Layout
@@ -0,0 +1,394 @@
1
+ import React from 'react'
2
+
3
+ import Layout from '../../pb_layout/_layout'
4
+ import Caption from '../../pb_caption/_caption'
5
+ import SectionSeparator from '../../pb_section_separator/_section_separator'
6
+
7
+ const teamData = {
8
+ eagles: {
9
+ avatar:"https://images.unsplash.com/photo-1628703117067-fb7c9c20946e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8ZWFnbGVzfGVufDB8fDB8fHww",
10
+ name:"Eagles",
11
+ rank:"#1 NFC East",
12
+ territory:"PHI",
13
+ },
14
+ packers: {
15
+ avatar:"https://images.unsplash.com/photo-1486297678162-eb2a19b0a32d?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
16
+ name:"Packers",
17
+ rank:"#3 NFC North",
18
+ territory:"GB",
19
+ },
20
+ vikings: {
21
+ avatar:"https://images.unsplash.com/photo-1525540796810-55f9fbc5592f?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTV8fHZpa2luZ3xlbnwwfHwwfHx8MA%3D%3D",
22
+ name:"Vikings",
23
+ rank:"#2 NFC North",
24
+ territory:"MIN",
25
+ },
26
+ rams: {
27
+ avatar:"https://images.unsplash.com/photo-1490739043913-239b6cdf4084?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
28
+ name:"Rams",
29
+ rank:"#1 NFC West",
30
+ territory:"LAR",
31
+ },
32
+ lions: {
33
+ avatar:"https://images.unsplash.com/photo-1614027164847-1b28cfe1df60?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
34
+ name:"Lions",
35
+ rank:"#1 NFC North",
36
+ territory:"DET",
37
+ },
38
+ commanders: {
39
+ avatar:"https://images.unsplash.com/photo-1501466044931-62695aada8e9?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
40
+ name:"Commanders",
41
+ rank:"#2 NFC East",
42
+ territory:"WAS",
43
+ },
44
+ buccaneers: {
45
+ avatar:"https://images.unsplash.com/photo-1584116843008-46d529f04145?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
46
+ name:"Buccaneers",
47
+ rank:"#1 NFC South",
48
+ territory:"TB",
49
+ },
50
+ chiefs: {
51
+ avatar:"https://plus.unsplash.com/premium_photo-1697729864667-57f5f29e946b?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8a2Fuc2FzJTIwY2l0eXxlbnwwfHwwfHx8MA%3D%3D",
52
+ name:"Chiefs",
53
+ rank:"#1 AFC West",
54
+ territory:"KC",
55
+ },
56
+ chargers: {
57
+ avatar:"https://images.unsplash.com/photo-1529310399831-ed472b81d589?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
58
+ name:"Chargers",
59
+ rank:"#2 AFC West",
60
+ territory:"LAC",
61
+ },
62
+ texans: {
63
+ avatar:"https://images.unsplash.com/photo-1545345540-ea5d968030af?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
64
+ name:"Texans",
65
+ rank:"#1 AFC South",
66
+ territory:"HOU",
67
+ },
68
+ broncos: {
69
+ avatar:"https://images.unsplash.com/photo-1553284965-83fd3e82fa5a?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
70
+ name:"Broncos",
71
+ rank:"#3 AFC West",
72
+ territory:"DEN",
73
+ },
74
+ bills: {
75
+ avatar:"https://images.unsplash.com/photo-1575414914265-ebc9aa2637f4?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
76
+ name:"Bills",
77
+ rank:"#1 AFC East",
78
+ territory:"BUF",
79
+ },
80
+ steelers: {
81
+ avatar:"https://plus.unsplash.com/premium_photo-1697730155764-cc8ca8f78cbe?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MXx8cGl0dHNidXJnaHxlbnwwfHwwfHx8MA%3D%3D",
82
+ name:"Steelers",
83
+ rank:"#2 AFC North",
84
+ territory:"PIT",
85
+ },
86
+ ravens: {
87
+ avatar:"https://images.unsplash.com/photo-1433888376991-1297486ba3f5?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8cmF2ZW58ZW58MHx8MHx8fDA%3D",
88
+ name:"Ravens",
89
+ rank:"#1 AFC North",
90
+ territory:"BAL",
91
+ },
92
+ bye: {
93
+ avatar:"",
94
+ name:"BYE",
95
+ rank:"",
96
+ territory:"",
97
+ },
98
+ }
99
+
100
+ const LayoutBracket = () => {
101
+ return (
102
+ <div>
103
+ <Layout
104
+ layout="bracket"
105
+ >
106
+ <Layout.RoundLabel>
107
+ <Caption>Wild Card</Caption>
108
+ <SectionSeparator marginY="sm"/>
109
+ </Layout.RoundLabel>
110
+ <Layout.Round marginBottom={{ xs: "md", sm: "md" }}>
111
+ <Layout.Game>
112
+ <Layout.Participant
113
+ avatar={teamData.packers.avatar}
114
+ name={teamData.packers.name}
115
+ points="10"
116
+ rank={teamData.packers.rank}
117
+ territory={teamData.packers.territory}
118
+ />
119
+ <Layout.Participant
120
+ avatar={teamData.eagles.avatar}
121
+ name={teamData.eagles.name}
122
+ points="22"
123
+ rank={teamData.eagles.rank}
124
+ self
125
+ territory={teamData.eagles.territory}
126
+ winner
127
+ />
128
+ </Layout.Game>
129
+ <Layout.Game>
130
+ <Layout.Participant
131
+ avatar={teamData.vikings.avatar}
132
+ name={teamData.vikings.name}
133
+ points="9"
134
+ rank={teamData.vikings.rank}
135
+ territory={teamData.vikings.territory}
136
+ />
137
+ <Layout.Participant
138
+ avatar={teamData.rams.avatar}
139
+ name={teamData.rams.name}
140
+ points="27"
141
+ rank={teamData.rams.rank}
142
+ territory={teamData.rams.territory}
143
+ winner
144
+ />
145
+ </Layout.Game>
146
+ <Layout.Game>
147
+ <Layout.Participant
148
+ avatar={teamData.lions.avatar}
149
+ name={teamData.lions.name}
150
+ points=""
151
+ rank={teamData.lions.rank}
152
+ territory={teamData.lions.territory}
153
+ winner
154
+ />
155
+ <Layout.Participant
156
+ avatar={teamData.bye.avatar}
157
+ name={teamData.bye.name}
158
+ points=""
159
+ rank={teamData.bye.rank}
160
+ territory={teamData.bye.territory}
161
+ />
162
+ </Layout.Game>
163
+ <Layout.Game>
164
+ <Layout.Participant
165
+ avatar={teamData.commanders.avatar}
166
+ name={teamData.commanders.name}
167
+ points="23"
168
+ rank={teamData.commanders.rank}
169
+ territory={teamData.commanders.territory}
170
+ winner
171
+ />
172
+ <Layout.Participant
173
+ avatar={teamData.buccaneers.avatar}
174
+ name={teamData.buccaneers.name}
175
+ points="20"
176
+ rank={teamData.buccaneers.rank}
177
+ territory={teamData.buccaneers.territory}
178
+ />
179
+ </Layout.Game>
180
+ <Layout.Game>
181
+ <Layout.Participant
182
+ avatar={teamData.chiefs.avatar}
183
+ name={teamData.chiefs.name}
184
+ points=""
185
+ rank={teamData.chiefs.rank}
186
+ territory={teamData.chiefs.territory}
187
+ winner
188
+ />
189
+ <Layout.Participant
190
+ avatar={teamData.bye.avatar}
191
+ name={teamData.bye.name}
192
+ points=""
193
+ rank={teamData.bye.rank}
194
+ territory={teamData.bye.territory}
195
+ />
196
+ </Layout.Game>
197
+ <Layout.Game>
198
+ <Layout.Participant
199
+ avatar={teamData.chargers.avatar}
200
+ name={teamData.chargers.name}
201
+ points="12"
202
+ rank={teamData.chargers.rank}
203
+ territory={teamData.chargers.territory}
204
+ />
205
+ <Layout.Participant
206
+ avatar={teamData.texans.avatar}
207
+ name={teamData.texans.name}
208
+ points="32"
209
+ rank={teamData.texans.rank}
210
+ territory={teamData.texans.territory}
211
+ winner
212
+ />
213
+ </Layout.Game>
214
+ <Layout.Game>
215
+ <Layout.Participant
216
+ avatar={teamData.broncos.avatar}
217
+ name={teamData.broncos.name}
218
+ points="7"
219
+ rank={teamData.broncos.rank}
220
+ territory={teamData.broncos.territory}
221
+ />
222
+ <Layout.Participant
223
+ avatar={teamData.bills.avatar}
224
+ name={teamData.bills.name}
225
+ points="31"
226
+ rank={teamData.bills.rank}
227
+ territory={teamData.bills.territory}
228
+ winner
229
+ />
230
+ </Layout.Game>
231
+ <Layout.Game>
232
+ <Layout.Participant
233
+ avatar={teamData.steelers.avatar}
234
+ name={teamData.steelers.name}
235
+ points="14"
236
+ rank={teamData.steelers.rank}
237
+ territory={teamData.steelers.territory}
238
+ />
239
+ <Layout.Participant
240
+ avatar={teamData.ravens.avatar}
241
+ name={teamData.ravens.name}
242
+ points="28"
243
+ rank={teamData.ravens.rank}
244
+ territory={teamData.ravens.territory}
245
+ winner
246
+ />
247
+ </Layout.Game>
248
+ </Layout.Round>
249
+ <Layout.RoundLabel>
250
+ <Caption>Divisional</Caption>
251
+ <SectionSeparator marginY="sm"/>
252
+ </Layout.RoundLabel>
253
+ <Layout.Round marginBottom={{ xs: "md", sm: "md" }}>
254
+ <Layout.Game>
255
+ <Layout.Participant
256
+ avatar={teamData.rams.avatar}
257
+ name={teamData.rams.name}
258
+ points="22"
259
+ rank={teamData.rams.rank}
260
+ territory={teamData.rams.territory}
261
+ />
262
+ <Layout.Participant
263
+ avatar={teamData.eagles.avatar}
264
+ name={teamData.eagles.name}
265
+ points="28"
266
+ rank={teamData.eagles.rank}
267
+ self
268
+ territory={teamData.eagles.territory}
269
+ winner
270
+ />
271
+ </Layout.Game>
272
+ <Layout.Game>
273
+ <Layout.Participant
274
+ avatar={teamData.commanders.avatar}
275
+ name={teamData.commanders.name}
276
+ points="45"
277
+ rank={teamData.commanders.rank}
278
+ territory={teamData.commanders.territory}
279
+ winner
280
+ />
281
+ <Layout.Participant
282
+ avatar={teamData.lions.avatar}
283
+ name={teamData.lions.name}
284
+ points="31"
285
+ rank={teamData.lions.rank}
286
+ territory={teamData.lions.territory}
287
+ />
288
+ </Layout.Game>
289
+ <Layout.Game>
290
+ <Layout.Participant
291
+ avatar={teamData.texans.avatar}
292
+ name={teamData.texans.name}
293
+ points="14"
294
+ rank={teamData.texans.rank}
295
+ territory={teamData.texans.territory}
296
+ />
297
+ <Layout.Participant
298
+ avatar={teamData.chiefs.avatar}
299
+ name={teamData.chiefs.name}
300
+ points="23"
301
+ rank={teamData.chiefs.rank}
302
+ territory={teamData.chiefs.territory}
303
+ winner
304
+ />
305
+ </Layout.Game>
306
+ <Layout.Game>
307
+ <Layout.Participant
308
+ avatar={teamData.ravens.avatar}
309
+ name={teamData.ravens.name}
310
+ points="25"
311
+ rank={teamData.ravens.rank}
312
+ territory={teamData.ravens.territory}
313
+ />
314
+ <Layout.Participant
315
+ avatar={teamData.bills.avatar}
316
+ name={teamData.bills.name}
317
+ points="27"
318
+ rank={teamData.bills.rank}
319
+ territory={teamData.bills.territory}
320
+ winner
321
+ />
322
+ </Layout.Game>
323
+ </Layout.Round>
324
+ <Layout.RoundLabel>
325
+ <Caption>Conference</Caption>
326
+ <SectionSeparator marginY="sm"/>
327
+ </Layout.RoundLabel>
328
+ <Layout.Round marginBottom={{ xs: "md", sm: "md" }}>
329
+ <Layout.Game>
330
+ <Layout.Participant
331
+ avatar={teamData.commanders.avatar}
332
+ name={teamData.commanders.name}
333
+ points="23"
334
+ rank={teamData.commanders.rank}
335
+ territory={teamData.commanders.territory}
336
+ />
337
+ <Layout.Participant
338
+ avatar={teamData.eagles.avatar}
339
+ name={teamData.eagles.name}
340
+ points="55"
341
+ rank={teamData.eagles.rank}
342
+ self
343
+ territory={teamData.eagles.territory}
344
+ winner
345
+ />
346
+ </Layout.Game>
347
+ <Layout.Game>
348
+ <Layout.Participant
349
+ avatar={teamData.bills.avatar}
350
+ name={teamData.bills.name}
351
+ points="29"
352
+ rank={teamData.bills.rank}
353
+ territory={teamData.bills.territory}
354
+ />
355
+ <Layout.Participant
356
+ avatar={teamData.chiefs.avatar}
357
+ name={teamData.chiefs.name}
358
+ points="32"
359
+ rank={teamData.chiefs.rank}
360
+ territory={teamData.chiefs.territory}
361
+ winner
362
+ />
363
+ </Layout.Game>
364
+ </Layout.Round>
365
+ <Layout.RoundLabel>
366
+ <Caption>Super Bowl</Caption>
367
+ <SectionSeparator marginY="sm"/>
368
+ </Layout.RoundLabel>
369
+ <Layout.Round>
370
+ <Layout.Game>
371
+ <Layout.Participant
372
+ avatar={teamData.chiefs.avatar}
373
+ name={teamData.chiefs.name}
374
+ points="22"
375
+ rank={teamData.chiefs.rank}
376
+ territory={teamData.chiefs.territory}
377
+ />
378
+ <Layout.Participant
379
+ avatar={teamData.eagles.avatar}
380
+ name={teamData.eagles.name}
381
+ points="40"
382
+ rank={teamData.eagles.rank}
383
+ self
384
+ territory={teamData.eagles.territory}
385
+ winner
386
+ />
387
+ </Layout.Game>
388
+ </Layout.Round>
389
+ </Layout>
390
+ </div>
391
+ )
392
+ }
393
+
394
+ export default LayoutBracket
@@ -0,0 +1,5 @@
1
+ Use `<Layout.RoundLabel>`, `<Layout.Round>`, `<Layout.Game>`, and/or `<Layout.Participant>` to make a bracket layout. Feel free to use custom components in place of the template components based on your needs.
2
+
3
+ On mobile devices, `<Layout.RoundLabel>` will display (on desktop these components are hidden) and the bracket will be in one column.
4
+
5
+ Ensure that each `<Layout.Game>` maintains a consistent height for the bracket lines to lay out properly.
@@ -18,4 +18,5 @@ examples:
18
18
  - layout_kanban: Kanban Layout
19
19
  - layout_content: Content Layout
20
20
  - layout_masonry: Masonry Layout
21
+ - layout_bracket: Bracket Layout
21
22
 
@@ -7,4 +7,5 @@ export { default as LayoutKanbanResponsive } from './_layout_kanban_responsive.j
7
7
  export { default as LayoutCollectionDetail } from './_layout_collection_detail.jsx'
8
8
  export { default as LayoutContent } from './_layout_content.jsx'
9
9
  export { default as LayoutMasonry } from './_layout_masonry.jsx'
10
+ export { default as LayoutBracket } from './_layout_bracket.jsx'
10
11
 
@@ -82,6 +82,10 @@ test("render all layout variants", () => {
82
82
  layout: "masonry",
83
83
  expected: "pb_layout_kit_masonry_size_md_left_light",
84
84
  },
85
+ {
86
+ layout: "bracket",
87
+ expected: "pb_layout_kit_bracket",
88
+ },
85
89
  ]
86
90
 
87
91
  testValues.forEach(({ layout, expected }) => {
@@ -0,0 +1,121 @@
1
+ import React from 'react'
2
+ import classnames from 'classnames'
3
+
4
+ import { GlobalProps, globalProps, globalInlineProps } from '../../utilities/globalProps'
5
+
6
+ import Card from '../../pb_card/_card'
7
+ import SectionSeparator from '../../pb_section_separator/_section_separator'
8
+ import Body from '../../pb_body/_body'
9
+ import Flex from '../../pb_flex/_flex'
10
+
11
+ type LayoutGameProps = {
12
+ children: React.ReactNode[] | React.ReactNode,
13
+ className?: string,
14
+ numberOfRounds: number,
15
+ numberOfGames: number,
16
+ lastRoundWithSelf?: number,
17
+ isOdd: boolean,
18
+ } & GlobalProps
19
+
20
+ // Game component (modeled after Item)
21
+ const Game = (props: LayoutGameProps) => {
22
+ const { children, className, numberOfRounds, numberOfGames, isOdd, lastRoundWithSelf } = props
23
+ const dynamicInlineProps = globalInlineProps(props)
24
+
25
+ const numberOfChildren = Array.isArray(children) ? children.length : 0
26
+
27
+ const isMultiple = Array.isArray(children)
28
+
29
+ let ratio = 0
30
+ let exponent
31
+ let currentRound = numberOfRounds
32
+ if (numberOfGames > 1) {
33
+ exponent = (numberOfRounds) - Math.log2(numberOfGames) - 1
34
+ ratio = 2 ** exponent
35
+
36
+ currentRound = exponent + 1
37
+ }
38
+
39
+ let hasWinner = false
40
+ const hasLastWinnerAndSelf = lastRoundWithSelf === currentRound
41
+ if (numberOfChildren === 2) {
42
+ const [firstChildWithoutProps, secondChildWithoutProps] = React.Children.toArray(children)
43
+
44
+ const firstChild = React.isValidElement(firstChildWithoutProps) ? React.cloneElement(firstChildWithoutProps, { hasLastWinnerAndSelf }) : firstChildWithoutProps
45
+ const secondChild = React.isValidElement(secondChildWithoutProps) ? React.cloneElement(secondChildWithoutProps, { hasLastWinnerAndSelf }) : secondChildWithoutProps
46
+
47
+ if (React.isValidElement(firstChild) && React.isValidElement(secondChild)) {
48
+ if (
49
+ firstChild?.props && typeof firstChild.props === 'object' && 'winner' in firstChild.props ||
50
+ secondChild?.props && typeof secondChild.props === 'object' && 'winner' in secondChild.props
51
+ ) {
52
+ hasWinner = true
53
+ }
54
+ return (
55
+ <div
56
+ className={classnames('layout_game', globalProps(props), className)}
57
+ style={dynamicInlineProps}
58
+ >
59
+ <Card
60
+ marginY="xs"
61
+ overflow="hidden"
62
+ padding="none"
63
+ shadow="deep"
64
+ >
65
+ <Card.Body padding="none">{firstChild}</Card.Body>
66
+ <SectionSeparator className="game_separator"/>
67
+ <Card.Body padding="none">{secondChild}</Card.Body>
68
+ </Card>
69
+ {isOdd && numberOfGames > 1 &&
70
+ <div
71
+ className="half_box"
72
+ style={{ height: `calc(${ratio} * 100% + 4px)` }}
73
+ />
74
+ }
75
+ {numberOfGames > 1 && hasWinner &&
76
+ <div className="polygon_node" />
77
+ }
78
+ </div>
79
+ )
80
+ }
81
+ }
82
+
83
+ return (
84
+ <div
85
+ className={classnames('layout_game', globalProps(props), className)}
86
+ style={dynamicInlineProps}
87
+ >
88
+ {((!isMultiple && children) || numberOfChildren >= 1) ? (
89
+ children
90
+ ) : (
91
+ <div className="layout_tbd">
92
+ <Card
93
+ marginY="xs"
94
+ padding="none"
95
+ shadow="deep"
96
+ >
97
+ <Card.Body padding="xs">
98
+ <Body color="light">
99
+ To be determined...
100
+ </Body>
101
+ </Card.Body>
102
+ <SectionSeparator className="game_separator"/>
103
+ <Card.Body padding="xs">
104
+ <Body color="light">
105
+ To be determined...
106
+ </Body>
107
+ </Card.Body>
108
+ </Card>
109
+ </div>
110
+ )}
111
+ {isOdd && numberOfGames > 1 &&
112
+ <div
113
+ className="half_box"
114
+ style={{ height: `calc(${ratio} * 100% + 4px)` }}
115
+ />
116
+ }
117
+ </div>
118
+ )
119
+ }
120
+
121
+ export default Game